From 388e883185cfc44289f6b8d8515c5002f0a7cb08 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 25 Jan 2020 17:02:03 +0100 Subject: [PATCH 1/3] Remove ampersand escape when writing to bib file Instead use save action to handle this case. Includes also a bit of refactoring (mostly renames). --- CHANGELOG.md | 1 + ...Parser.java => FieldContentFormatter.java} | 9 +- ... => FieldContentFormatterPreferences.java} | 6 +- .../org/jabref/logic/bibtex/FieldWriter.java | 82 +++------------- .../logic/bibtex/FieldWriterPreferences.java | 12 +-- .../jabref/logic/formatter/Formatters.java | 2 + .../EscapeAmpersandsFormatter.java | 95 +++++++++++++++++++ .../importer/ImportFormatPreferences.java | 16 ++-- .../importer/fileformat/BibtexParser.java | 10 +- .../jabref/preferences/JabRefPreferences.java | 8 +- .../jabref/gui/entryeditor/SourceTabTest.java | 6 +- .../gui/exporter/SaveDatabaseActionTest.java | 6 +- ...st.java => FieldContentFormatterTest.java} | 16 ++-- .../jabref/logic/bibtex/FieldWriterTests.java | 2 +- .../EscapeAmpersandsFormatterTest.java | 31 ++++++ .../EscapeUnderscoresFormatterTest.java | 16 +--- .../fetcher/ACMPortalFetcherTest.java | 4 +- .../fetcher/AstrophysicsDataSystemTest.java | 6 +- .../importer/fetcher/DBLPFetcherTest.java | 6 +- .../importer/fetcher/GoogleScholarTest.java | 6 +- .../importer/fetcher/INSPIREFetcherTest.java | 4 +- .../importer/fetcher/MathSciNetTest.java | 6 +- .../logic/importer/fetcher/ZbMATHTest.java | 6 +- .../importer/fileformat/BibtexParserTest.java | 10 +- 24 files changed, 216 insertions(+), 150 deletions(-) rename src/main/java/org/jabref/logic/bibtex/{FieldContentParser.java => FieldContentFormatter.java} (88%) rename src/main/java/org/jabref/logic/bibtex/{FieldContentParserPreferences.java => FieldContentFormatterPreferences.java} (73%) create mode 100644 src/main/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatter.java rename src/test/java/org/jabref/logic/bibtex/{FieldContentParserTest.java => FieldContentFormatterTest.java} (78%) create mode 100644 src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c60e7a0e5a8..91b596d947f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We fixed an issue where the file extension was missing after downloading a file (we now fall-back to pdf). [#5816](https://github.com/JabRef/jabref/issues/5816) ### Removed +- Ampersands are no longer escaped by default in the `bib` file. If you want to keep the current behaviour, you can use the new "Escape Ampersands" formatter as a save action. ## [5.0-beta] – 2019-12-15 diff --git a/src/main/java/org/jabref/logic/bibtex/FieldContentParser.java b/src/main/java/org/jabref/logic/bibtex/FieldContentFormatter.java similarity index 88% rename from src/main/java/org/jabref/logic/bibtex/FieldContentParser.java rename to src/main/java/org/jabref/logic/bibtex/FieldContentFormatter.java index 92d34ecf0fd..5b2a2c6171d 100644 --- a/src/main/java/org/jabref/logic/bibtex/FieldContentParser.java +++ b/src/main/java/org/jabref/logic/bibtex/FieldContentFormatter.java @@ -15,16 +15,15 @@ * in JabRef style. The reformatting must undo all formatting done by JabRef when * writing the same fields. */ -public class FieldContentParser { +public class FieldContentFormatter { // 's' matches a space, tab, new line, carriage return. private static final Pattern WHITESPACE = Pattern.compile("\\s+"); private final Set multiLineFields; - - public FieldContentParser(FieldContentParserPreferences prefs) { - Objects.requireNonNull(prefs); + public FieldContentFormatter(FieldContentFormatterPreferences preferences) { + Objects.requireNonNull(preferences); multiLineFields = new HashSet<>(); // the following two are also coded in org.jabref.logic.bibtex.LatexFieldFormatter.format(String, String) @@ -32,7 +31,7 @@ public FieldContentParser(FieldContentParserPreferences prefs) { multiLineFields.add(StandardField.COMMENT); multiLineFields.add(StandardField.REVIEW); // the file field should not be formatted, therefore we treat it as a multi line field - multiLineFields.addAll(prefs.getNonWrappableFields()); + multiLineFields.addAll(preferences.getNonWrappableFields()); } /** diff --git a/src/main/java/org/jabref/logic/bibtex/FieldContentParserPreferences.java b/src/main/java/org/jabref/logic/bibtex/FieldContentFormatterPreferences.java similarity index 73% rename from src/main/java/org/jabref/logic/bibtex/FieldContentParserPreferences.java rename to src/main/java/org/jabref/logic/bibtex/FieldContentFormatterPreferences.java index 4abf89d3c8d..26f13248b85 100644 --- a/src/main/java/org/jabref/logic/bibtex/FieldContentParserPreferences.java +++ b/src/main/java/org/jabref/logic/bibtex/FieldContentFormatterPreferences.java @@ -5,16 +5,16 @@ import org.jabref.model.entry.field.Field; -public class FieldContentParserPreferences { +public class FieldContentFormatterPreferences { private final List nonWrappableFields; - public FieldContentParserPreferences() { + public FieldContentFormatterPreferences() { // This constructor is only to allow an empty constructor in SavePreferences this.nonWrappableFields = Collections.emptyList(); } - public FieldContentParserPreferences(List nonWrappableFields) { + public FieldContentFormatterPreferences(List nonWrappableFields) { this.nonWrappableFields = nonWrappableFields; } diff --git a/src/main/java/org/jabref/logic/bibtex/FieldWriter.java b/src/main/java/org/jabref/logic/bibtex/FieldWriter.java index 732d3a3941e..e0ddfc9ace0 100644 --- a/src/main/java/org/jabref/logic/bibtex/FieldWriter.java +++ b/src/main/java/org/jabref/logic/bibtex/FieldWriter.java @@ -17,19 +17,19 @@ public class FieldWriter { private static final char FIELD_START = '{'; private static final char FIELD_END = '}'; private final boolean neverFailOnHashes; - private final FieldWriterPreferences prefs; - private final FieldContentParser parser; + private final FieldWriterPreferences preferences; + private final FieldContentFormatter formatter; private StringBuilder stringBuilder; - public FieldWriter(FieldWriterPreferences prefs) { - this(true, prefs); + public FieldWriter(FieldWriterPreferences preferences) { + this(true, preferences); } - private FieldWriter(boolean neverFailOnHashes, FieldWriterPreferences prefs) { + private FieldWriter(boolean neverFailOnHashes, FieldWriterPreferences preferences) { this.neverFailOnHashes = neverFailOnHashes; - this.prefs = prefs; + this.preferences = preferences; - parser = new FieldContentParser(prefs.getFieldContentParserPreferences()); + formatter = new FieldContentFormatter(preferences.getFieldContentFormatterPreferences()); } public static FieldWriter buildIgnoreHashes(FieldWriterPreferences prefs) { @@ -152,13 +152,13 @@ private String formatAndResolveStrings(String content, Field field) throws Inval } } - return parser.format(stringBuilder, field); + return formatter.format(stringBuilder, field); } private boolean shouldResolveStrings(Field field) { - if (prefs.isResolveStringsAllFields()) { + if (preferences.isResolveStringsAllFields()) { // Resolve strings for all fields except some: - return !prefs.getDoNotResolveStringsFor().contains(field); + return !preferences.getDoNotResolveStringsFor().contains(field); } else { // Default operation - we only resolve strings for standard fields: return field instanceof StandardField || InternalField.BIBTEX_STRING.equals(field); @@ -170,7 +170,7 @@ private String formatWithoutResolvingStrings(String content, Field field) throws stringBuilder = new StringBuilder(String.valueOf(FIELD_START)); - stringBuilder.append(parser.format(content, field)); + stringBuilder.append(formatter.format(content, field)); stringBuilder.append(FIELD_END); @@ -179,63 +179,7 @@ private String formatWithoutResolvingStrings(String content, Field field) throws private void writeText(String text, int startPos, int endPos) { stringBuilder.append(FIELD_START); - boolean escape = false; - boolean inCommandName = false; - boolean inCommand = false; - boolean inCommandOption = false; - int nestedEnvironments = 0; - StringBuilder commandName = new StringBuilder(); - for (int i = startPos; i < endPos; i++) { - char c = text.charAt(i); - - // Track whether we are in a LaTeX command of some sort. - if (Character.isLetter(c) && (escape || inCommandName)) { - inCommandName = true; - if (!inCommandOption) { - commandName.append(c); - } - } else if (Character.isWhitespace(c) && (inCommand || inCommandOption)) { - // Whitespace - } else if (inCommandName) { - // This means the command name is ended. - // Perhaps the beginning of an argument: - if (c == '[') { - inCommandOption = true; - } else if (inCommandOption && (c == ']')) { - // Or the end of an argument: - inCommandOption = false; - } else if (!inCommandOption && (c == '{')) { - inCommandName = false; - inCommand = true; - } else { - // Or simply the end of this command alltogether: - commandName.delete(0, commandName.length()); - inCommandName = false; - } - } - // If we are in a command body, see if it has ended: - if (inCommand && (c == '}')) { - if ("begin".equals(commandName.toString())) { - nestedEnvironments++; - } - if ((nestedEnvironments > 0) && "end".equals(commandName.toString())) { - nestedEnvironments--; - } - - commandName.delete(0, commandName.length()); - inCommand = false; - } - - // We add a backslash before any ampersand characters, with one exception: if - // we are inside an \\url{...} command, we should write it as it is. Maybe. - if ((c == '&') && !escape && !(inCommand && "url".equals(commandName.toString())) - && (nestedEnvironments == 0)) { - stringBuilder.append("\\&"); - } else { - stringBuilder.append(c); - } - escape = c == '\\'; - } + stringBuilder.append(text, startPos, endPos); stringBuilder.append(FIELD_END); } @@ -245,7 +189,7 @@ private void writeStringLabel(String text, int startPos, int endPos, boolean fir } private void putIn(String s) { - stringBuilder.append(StringUtil.wrap(s, prefs.getLineLength(), OS.NEWLINE)); + stringBuilder.append(StringUtil.wrap(s, preferences.getLineLength(), OS.NEWLINE)); } } diff --git a/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java b/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java index 0776160d6d2..5caaa76de1b 100644 --- a/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java +++ b/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java @@ -10,18 +10,18 @@ public class FieldWriterPreferences { private final boolean resolveStringsAllFields; private final List doNotResolveStringsFor; private final int lineLength = 65; // Constant - private final FieldContentParserPreferences fieldContentParserPreferences; + private final FieldContentFormatterPreferences fieldContentFormatterPreferences; public FieldWriterPreferences(boolean resolveStringsAllFields, List doNotResolveStringsFor, - FieldContentParserPreferences fieldContentParserPreferences) { + FieldContentFormatterPreferences fieldContentFormatterPreferences) { this.resolveStringsAllFields = resolveStringsAllFields; this.doNotResolveStringsFor = doNotResolveStringsFor; - this.fieldContentParserPreferences = fieldContentParserPreferences; + this.fieldContentFormatterPreferences = fieldContentFormatterPreferences; } public FieldWriterPreferences() { // This constructor is only to allow an empty constructor in SavePreferences - this(true, Collections.emptyList(), new FieldContentParserPreferences()); + this(true, Collections.emptyList(), new FieldContentFormatterPreferences()); } public boolean isResolveStringsAllFields() { @@ -36,7 +36,7 @@ public int getLineLength() { return lineLength; } - public FieldContentParserPreferences getFieldContentParserPreferences() { - return fieldContentParserPreferences; + public FieldContentFormatterPreferences getFieldContentFormatterPreferences() { + return fieldContentFormatterPreferences; } } diff --git a/src/main/java/org/jabref/logic/formatter/Formatters.java b/src/main/java/org/jabref/logic/formatter/Formatters.java index 55a91f7f86c..b4ea94dad43 100644 --- a/src/main/java/org/jabref/logic/formatter/Formatters.java +++ b/src/main/java/org/jabref/logic/formatter/Formatters.java @@ -8,6 +8,7 @@ import org.jabref.logic.formatter.bibtexfields.CleanupUrlFormatter; import org.jabref.logic.formatter.bibtexfields.ClearFormatter; +import org.jabref.logic.formatter.bibtexfields.EscapeAmpersandsFormatter; import org.jabref.logic.formatter.bibtexfields.EscapeUnderscoresFormatter; import org.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import org.jabref.logic.formatter.bibtexfields.HtmlToUnicodeFormatter; @@ -69,6 +70,7 @@ public static List getOthers() { new RemoveBracesFormatter(), new UnitsToLatexFormatter(), new EscapeUnderscoresFormatter(), + new EscapeAmpersandsFormatter(), new ShortenDOIFormatter() ); } diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatter.java new file mode 100644 index 00000000000..75f08042b90 --- /dev/null +++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatter.java @@ -0,0 +1,95 @@ +package org.jabref.logic.formatter.bibtexfields; + +import java.util.Objects; + +import org.jabref.logic.l10n.Localization; +import org.jabref.model.cleanup.Formatter; + +public class EscapeAmpersandsFormatter extends Formatter { + + @Override + public String getName() { + return Localization.lang("Escape ampersands"); + } + + @Override + public String getKey() { + return "escapeAmpersands"; + } + + @Override + public String format(String value) { + Objects.requireNonNull(value); + + StringBuilder result = new StringBuilder(); + + boolean escape = false; + boolean inCommandName = false; + boolean inCommand = false; + boolean inCommandOption = false; + int nestedEnvironments = 0; + StringBuilder commandName = new StringBuilder(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + + // Track whether we are in a LaTeX command of some sort. + if (Character.isLetter(c) && (escape || inCommandName)) { + inCommandName = true; + if (!inCommandOption) { + commandName.append(c); + } + } else if (Character.isWhitespace(c) && (inCommand || inCommandOption)) { + // Whitespace + } else if (inCommandName) { + // This means the command name is ended. + // Perhaps the beginning of an argument: + if (c == '[') { + inCommandOption = true; + } else if (inCommandOption && (c == ']')) { + // Or the end of an argument: + inCommandOption = false; + } else if (!inCommandOption && (c == '{')) { + inCommandName = false; + inCommand = true; + } else { + // Or simply the end of this command alltogether: + commandName.delete(0, commandName.length()); + inCommandName = false; + } + } + // If we are in a command body, see if it has ended: + if (inCommand && (c == '}')) { + if ("begin".equals(commandName.toString())) { + nestedEnvironments++; + } + if ((nestedEnvironments > 0) && "end".equals(commandName.toString())) { + nestedEnvironments--; + } + + commandName.delete(0, commandName.length()); + inCommand = false; + } + + // We add a backslash before any ampersand characters, with one exception: if + // we are inside an \\url{...} command, we should write it as it is. Maybe. + if ((c == '&') && !escape && !(inCommand && "url".equals(commandName.toString())) + && (nestedEnvironments == 0)) { + result.append("\\&"); + } else { + result.append(c); + } + escape = c == '\\'; + } + return result.toString(); + } + + @Override + public String getDescription() { + return Localization.lang("Escape ampersands"); + } + + @Override + public String getExampleInput() { + return "Text & with &ersands"; + } +} diff --git a/src/main/java/org/jabref/logic/importer/ImportFormatPreferences.java b/src/main/java/org/jabref/logic/importer/ImportFormatPreferences.java index 2bb90b382fc..35aea8e66d9 100644 --- a/src/main/java/org/jabref/logic/importer/ImportFormatPreferences.java +++ b/src/main/java/org/jabref/logic/importer/ImportFormatPreferences.java @@ -3,7 +3,7 @@ import java.nio.charset.Charset; import java.util.Set; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; import org.jabref.logic.importer.fileformat.CustomImporter; import org.jabref.logic.xmp.XmpPreferences; @@ -14,18 +14,18 @@ public class ImportFormatPreferences { private final Charset encoding; private final Character keywordSeparator; private final BibtexKeyPatternPreferences bibtexKeyPatternPreferences; - private final FieldContentParserPreferences fieldContentParserPreferences; + private final FieldContentFormatterPreferences fieldContentFormatterPreferences; private final XmpPreferences xmpPreferences; private final boolean keywordSyncEnabled; public ImportFormatPreferences(Set customImportList, Charset encoding, Character keywordSeparator, - BibtexKeyPatternPreferences bibtexKeyPatternPreferences, - FieldContentParserPreferences fieldContentParserPreferences, XmpPreferences xmpPreferences, boolean keywordSyncEnabled) { + BibtexKeyPatternPreferences bibtexKeyPatternPreferences, + FieldContentFormatterPreferences fieldContentFormatterPreferences, XmpPreferences xmpPreferences, boolean keywordSyncEnabled) { this.customImportList = customImportList; this.encoding = encoding; this.keywordSeparator = keywordSeparator; this.bibtexKeyPatternPreferences = bibtexKeyPatternPreferences; - this.fieldContentParserPreferences = fieldContentParserPreferences; + this.fieldContentFormatterPreferences = fieldContentFormatterPreferences; this.xmpPreferences = xmpPreferences; this.keywordSyncEnabled = keywordSyncEnabled; } @@ -50,13 +50,13 @@ public BibtexKeyPatternPreferences getBibtexKeyPatternPreferences() { return bibtexKeyPatternPreferences; } - public FieldContentParserPreferences getFieldContentParserPreferences() { - return fieldContentParserPreferences; + public FieldContentFormatterPreferences getFieldContentFormatterPreferences() { + return fieldContentFormatterPreferences; } public ImportFormatPreferences withEncoding(Charset newEncoding) { return new ImportFormatPreferences(customImportList, newEncoding, keywordSeparator, bibtexKeyPatternPreferences, - fieldContentParserPreferences, xmpPreferences, keywordSyncEnabled); + fieldContentFormatterPreferences, xmpPreferences, keywordSyncEnabled); } /** diff --git a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java index 0fb4526f741..0934f841398 100644 --- a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java +++ b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java @@ -20,7 +20,7 @@ import java.util.Set; import java.util.regex.Pattern; -import org.jabref.logic.bibtex.FieldContentParser; +import org.jabref.logic.bibtex.FieldContentFormatter; import org.jabref.logic.exporter.BibtexDatabaseWriter; import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.importer.ImportFormatPreferences; @@ -65,7 +65,7 @@ public class BibtexParser implements Parser { private static final Logger LOGGER = LoggerFactory.getLogger(BibtexParser.class); private static final Integer LOOKAHEAD = 64; - private final FieldContentParser fieldContentParser; + private final FieldContentFormatter fieldContentFormatter; private final Deque pureTextFromFile = new LinkedList<>(); private final ImportFormatPreferences importFormatPreferences; private PushbackReader pushbackReader; @@ -78,7 +78,7 @@ public class BibtexParser implements Parser { public BibtexParser(ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor) { this.importFormatPreferences = Objects.requireNonNull(importFormatPreferences); - fieldContentParser = new FieldContentParser(importFormatPreferences.getFieldContentParserPreferences()); + fieldContentFormatter = new FieldContentFormatter(importFormatPreferences.getFieldContentFormatterPreferences()); metaDataParser = new MetaDataParser(fileMonitor); } @@ -594,13 +594,13 @@ private String parseFieldContent(Field field) throws IOException { } if (character == '"') { StringBuilder text = parseQuotedFieldExactly(); - value.append(fieldContentParser.format(text, field)); + value.append(fieldContentFormatter.format(text, field)); } else if (character == '{') { // Value is a string enclosed in brackets. There can be pairs // of brackets inside of a field, so we need to count the // brackets to know when the string is finished. StringBuilder text = parseBracketedTextExactly(); - value.append(fieldContentParser.format(text, field)); + value.append(fieldContentFormatter.format(text, field)); } else if (Character.isDigit((char) character)) { // value is a number String number = parseTextToken(); value.append(number); diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index c62345a312d..8170d2881bb 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -54,7 +54,7 @@ import org.jabref.gui.push.PushToApplicationsManager; import org.jabref.gui.specialfields.SpecialFieldsPreferences; import org.jabref.gui.util.ThemeLoader; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.bibtex.FieldWriterPreferences; import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences; import org.jabref.logic.citationstyle.CitationStyle; @@ -1440,14 +1440,14 @@ public FieldWriterPreferences getFieldWriterPreferences() { getFieldContentParserPreferences()); } - public FieldContentParserPreferences getFieldContentParserPreferences() { - return new FieldContentParserPreferences(getStringList(NON_WRAPPABLE_FIELDS).stream().map(FieldFactory::parseField).collect(Collectors.toList())); + public FieldContentFormatterPreferences getFieldContentParserPreferences() { + return new FieldContentFormatterPreferences(getStringList(NON_WRAPPABLE_FIELDS).stream().map(FieldFactory::parseField).collect(Collectors.toList())); } @Override public boolean isKeywordSyncEnabled() { return getBoolean(JabRefPreferences.SPECIALFIELDSENABLED) - && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); + && getBoolean(JabRefPreferences.AUTOSYNCSPECIALFIELDSTOKEYWORDS); } @Override diff --git a/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java b/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java index da779de6c24..b2d9f71ea0d 100644 --- a/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java +++ b/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java @@ -13,7 +13,7 @@ import org.jabref.gui.keyboard.KeyBindingRepository; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.OptionalObjectProperty; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.bibtex.FieldWriterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.database.BibDatabaseContext; @@ -50,8 +50,8 @@ public void onStart(Stage stage) { when(stateManager.activeSearchQueryProperty()).thenReturn(OptionalObjectProperty.empty()); KeyBindingRepository keyBindingRepository = new KeyBindingRepository(Collections.emptyList(), Collections.emptyList()); ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()) - .thenReturn(mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()) + .thenReturn(mock(FieldContentFormatterPreferences.class)); sourceTab = new SourceTab(new BibDatabaseContext(), new CountingUndoManager(), new FieldWriterPreferences(), importFormatPreferences, new DummyFileUpdateMonitor(), mock(DialogService.class), stateManager, keyBindingRepository); pane = new TabPane( diff --git a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java index eef64da0e42..6afed9d0c01 100644 --- a/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java +++ b/src/test/java/org/jabref/gui/exporter/SaveDatabaseActionTest.java @@ -15,7 +15,7 @@ import org.jabref.gui.JabRefFrame; import org.jabref.gui.undo.CountingUndoManager; import org.jabref.gui.util.FileDialogConfiguration; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.bibtex.FieldWriterPreferences; import org.jabref.logic.exporter.SavePreferences; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; @@ -112,7 +112,7 @@ private SaveDatabaseAction createSaveDatabaseActionForBibDatabase(BibDatabase da file.toFile().deleteOnExit(); FieldWriterPreferences fieldWriterPreferences = mock(FieldWriterPreferences.class); - when(fieldWriterPreferences.getFieldContentParserPreferences()).thenReturn(mock(FieldContentParserPreferences.class)); + when(fieldWriterPreferences.getFieldContentFormatterPreferences()).thenReturn(mock(FieldContentFormatterPreferences.class)); SavePreferences savePreferences = mock(SavePreferences.class); // In case a "thenReturn" is modified, the whole mock has to be recreated dbContext = mock(BibDatabaseContext.class); @@ -132,7 +132,7 @@ private SaveDatabaseAction createSaveDatabaseActionForBibDatabase(BibDatabase da when(dbContext.getEntries()).thenReturn(database.getEntries()); when(preferences.getBoolean(JabRefPreferences.LOCAL_AUTO_SAVE)).thenReturn(false); when(preferences.getDefaultEncoding()).thenReturn(StandardCharsets.UTF_8); - when(preferences.getFieldContentParserPreferences()).thenReturn(mock(FieldContentParserPreferences.class)); + when(preferences.getFieldContentParserPreferences()).thenReturn(mock(FieldContentFormatterPreferences.class)); when(preferences.loadForSaveFromPreferences()).thenReturn(savePreferences); when(basePanel.frame()).thenReturn(jabRefFrame); when(basePanel.getBibDatabaseContext()).thenReturn(dbContext); diff --git a/src/test/java/org/jabref/logic/bibtex/FieldContentParserTest.java b/src/test/java/org/jabref/logic/bibtex/FieldContentFormatterTest.java similarity index 78% rename from src/test/java/org/jabref/logic/bibtex/FieldContentParserTest.java rename to src/test/java/org/jabref/logic/bibtex/FieldContentFormatterTest.java index 2881ee366f3..cf0402421bd 100644 --- a/src/test/java/org/jabref/logic/bibtex/FieldContentParserTest.java +++ b/src/test/java/org/jabref/logic/bibtex/FieldContentFormatterTest.java @@ -11,18 +11,18 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class FieldContentParserTest { +class FieldContentFormatterTest { - private FieldContentParser parser; + private FieldContentFormatter parser; @BeforeEach - public void setUp() throws Exception { - FieldContentParserPreferences prefs = new FieldContentParserPreferences(Collections.emptyList()); - parser = new FieldContentParser(prefs); + void setUp() throws Exception { + FieldContentFormatterPreferences preferences = new FieldContentFormatterPreferences(Collections.emptyList()); + parser = new FieldContentFormatter(preferences); } @Test - public void unifiesLineBreaks() { + void unifiesLineBreaks() { String original = "I\r\nunify\nline\rbreaks."; String expected = "I\nunify\nline\nbreaks.".replace("\n", OS.NEWLINE); String processed = parser.format(new StringBuilder(original), StandardField.ABSTRACT); @@ -31,7 +31,7 @@ public void unifiesLineBreaks() { } @Test - public void retainsWhitespaceForMultiLineFields() { + void retainsWhitespaceForMultiLineFields() { String original = "I\nkeep\nline\nbreaks\nand\n\ttabs."; String formatted = original.replace("\n", OS.NEWLINE); @@ -43,7 +43,7 @@ public void retainsWhitespaceForMultiLineFields() { } @Test - public void removeWhitespaceFromNonMultiLineFields() { + void removeWhitespaceFromNonMultiLineFields() { String original = "I\nshould\nnot\ninclude\nadditional\nwhitespaces \nor\n\ttabs."; String expected = "I should not include additional whitespaces or tabs."; diff --git a/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java b/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java index 2dfdca2edc0..9480c8c500b 100644 --- a/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java +++ b/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java @@ -116,7 +116,7 @@ void hashEnclosedWordsGetRealStringsInMonthField() throws Exception { @Test void hashEnclosedWordsGetRealStringsInMonthFieldBecauseMonthIsStandardField() throws Exception { FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences( - false, Collections.emptyList(), new FieldContentParserPreferences()); + false, Collections.emptyList(), new FieldContentFormatterPreferences()); FieldWriter formatter = new FieldWriter(fieldWriterPreferences); String text = "#jan# - #feb#"; assertEquals("jan #{ - } # feb", formatter.write(StandardField.MONTH, text)); diff --git a/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatterTest.java b/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatterTest.java new file mode 100644 index 00000000000..2e1a3d6b222 --- /dev/null +++ b/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeAmpersandsFormatterTest.java @@ -0,0 +1,31 @@ +package org.jabref.logic.formatter.bibtexfields; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EscapeAmpersandsFormatterTest { + + private EscapeAmpersandsFormatter formatter; + + @BeforeEach + void setUp() { + formatter = new EscapeAmpersandsFormatter(); + } + + @Test + void formatReturnsSameTextIfNoAmpersandsPresent() throws Exception { + assertEquals("Lorem ipsum", formatter.format("Lorem ipsum")); + } + + @Test + void formatEscapesAmpersandsIfPresent() throws Exception { + assertEquals("Lorem\\&ipsum", formatter.format("Lorem&ipsum")); + } + + @Test + void formatExample() { + assertEquals("Text \\& with \\&ersands", formatter.format(formatter.getExampleInput())); + } +} diff --git a/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeUnderscoresFormatterTest.java b/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeUnderscoresFormatterTest.java index bfd2312ff87..2c756e7eebf 100644 --- a/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeUnderscoresFormatterTest.java +++ b/src/test/java/org/jabref/logic/formatter/bibtexfields/EscapeUnderscoresFormatterTest.java @@ -5,33 +5,27 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class EscapeUnderscoresFormatterTest { +class EscapeUnderscoresFormatterTest { private EscapeUnderscoresFormatter formatter; @BeforeEach - public void setUp() { + void setUp() { formatter = new EscapeUnderscoresFormatter(); } - /** - * Check whether the clear formatter really returns the empty string for the empty string - */ @Test - public void formatReturnsSameTextIfNoUnderscoresPresent() throws Exception { + void formatReturnsSameTextIfNoUnderscoresPresent() throws Exception { assertEquals("Lorem ipsum", formatter.format("Lorem ipsum")); } - /** - * Check whether the clear formatter really returns the empty string for some string - */ @Test - public void formatEscapesUnderscoresIfPresent() throws Exception { + void formatEscapesUnderscoresIfPresent() throws Exception { assertEquals("Lorem\\_ipsum", formatter.format("Lorem_ipsum")); } @Test - public void formatExample() { + void formatExample() { assertEquals("Text\\_with\\_underscores", formatter.format(formatter.getExampleInput())); } } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ACMPortalFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ACMPortalFetcherTest.java index 25e1c6dbd30..ebb1af773d2 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ACMPortalFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ACMPortalFetcherTest.java @@ -3,7 +3,7 @@ import java.util.Collections; import java.util.List; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -27,7 +27,7 @@ class ACMPortalFetcherTest { @BeforeEach void setUp() { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn(mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn(mock(FieldContentFormatterPreferences.class)); fetcher = new ACMPortalFetcher(importFormatPreferences); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java b/src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java index 08e70e03a2b..78e99bf780a 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java @@ -3,7 +3,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -28,8 +28,8 @@ public class AstrophysicsDataSystemTest { @BeforeEach public void setUp() throws Exception { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn( - mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn( + mock(FieldContentFormatterPreferences.class)); fetcher = new AstrophysicsDataSystem(importFormatPreferences); diezSliceTheoremEntry = new BibEntry(); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/DBLPFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/DBLPFetcherTest.java index 8618818fbd5..d48c46f3f7e 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/DBLPFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/DBLPFetcherTest.java @@ -3,7 +3,7 @@ import java.util.Collections; import java.util.List; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; @@ -28,8 +28,8 @@ public class DBLPFetcherTest { @BeforeEach public void setUp() { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()) - .thenReturn(mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()) + .thenReturn(mock(FieldContentFormatterPreferences.class)); dblpFetcher = new DBLPFetcher(importFormatPreferences); entry = new BibEntry(); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java index 7c4be8d3848..1eec09aab49 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/GoogleScholarTest.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; @@ -31,8 +31,8 @@ class GoogleScholarTest { @BeforeEach void setUp() { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn( - mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn( + mock(FieldContentFormatterPreferences.class)); finder = new GoogleScholar(importFormatPreferences); entry = new BibEntry(); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/INSPIREFetcherTest.java b/src/test/java/org/jabref/logic/importer/fetcher/INSPIREFetcherTest.java index e9508e936d4..34e900d7d1e 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/INSPIREFetcherTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/INSPIREFetcherTest.java @@ -3,7 +3,7 @@ import java.util.Arrays; import java.util.List; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -26,7 +26,7 @@ class INSPIREFetcherTest { @BeforeEach void setUp() { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn(mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn(mock(FieldContentFormatterPreferences.class)); fetcher = new INSPIREFetcher(importFormatPreferences); } diff --git a/src/test/java/org/jabref/logic/importer/fetcher/MathSciNetTest.java b/src/test/java/org/jabref/logic/importer/fetcher/MathSciNetTest.java index 75b7d616282..74979971e16 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/MathSciNetTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/MathSciNetTest.java @@ -4,7 +4,7 @@ import java.util.List; import java.util.Optional; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -29,8 +29,8 @@ class MathSciNetTest { @BeforeEach void setUp() throws Exception { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn( - mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn( + mock(FieldContentFormatterPreferences.class)); fetcher = new MathSciNet(importFormatPreferences); ratiuEntry = new BibEntry(); diff --git a/src/test/java/org/jabref/logic/importer/fetcher/ZbMATHTest.java b/src/test/java/org/jabref/logic/importer/fetcher/ZbMATHTest.java index 35e387fe926..7a9c140fc00 100644 --- a/src/test/java/org/jabref/logic/importer/fetcher/ZbMATHTest.java +++ b/src/test/java/org/jabref/logic/importer/fetcher/ZbMATHTest.java @@ -3,7 +3,7 @@ import java.util.Collections; import java.util.List; -import org.jabref.logic.bibtex.FieldContentParserPreferences; +import org.jabref.logic.bibtex.FieldContentFormatterPreferences; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; @@ -27,8 +27,8 @@ class ZbMATHTest { @BeforeEach void setUp() throws Exception { ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class); - when(importFormatPreferences.getFieldContentParserPreferences()).thenReturn( - mock(FieldContentParserPreferences.class)); + when(importFormatPreferences.getFieldContentFormatterPreferences()).thenReturn( + mock(FieldContentFormatterPreferences.class)); fetcher = new ZbMATH(importFormatPreferences); donaldsonEntry = new BibEntry(); diff --git a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java index b5780306e55..21eaf51c321 100644 --- a/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java +++ b/src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java @@ -1105,7 +1105,7 @@ void parseConvertsMultipleTabsToSpace() throws IOException { @Test void parsePreservesMultipleSpacesInNonWrappableField() throws IOException { - when(importFormatPreferences.getFieldContentParserPreferences().getNonWrappableFields()) + when(importFormatPreferences.getFieldContentFormatterPreferences().getNonWrappableFields()) .thenReturn(Collections.singletonList(StandardField.FILE)); BibtexParser parser = new BibtexParser(importFormatPreferences, fileMonitor); ParserResult result = parser @@ -1140,7 +1140,7 @@ void parsePreservesNewlineInAbstractField() throws IOException { @Test void parseHandlesAccentsCorrectly() throws IOException { ParserResult result = parser - .parse(new StringReader("@article{test,author = {H\'{e}lne Fiaux}}")); + .parse(new StringReader("@article{test,author = {H'{e}lne Fiaux}}")); Collection parsedEntries = result.getDatabase().getEntries(); BibEntry parsedEntry = parsedEntries.iterator().next(); @@ -1149,7 +1149,7 @@ void parseHandlesAccentsCorrectly() throws IOException { assertEquals(1, parsedEntries.size()); assertEquals(StandardEntryType.Article, parsedEntry.getType()); assertEquals(Optional.of("test"), parsedEntry.getCiteKeyOptional()); - assertEquals(Optional.of("H\'{e}lne Fiaux"), parsedEntry.getField(StandardField.AUTHOR)); + assertEquals(Optional.of("H'{e}lne Fiaux"), parsedEntry.getField(StandardField.AUTHOR)); } /** @@ -1158,7 +1158,7 @@ void parseHandlesAccentsCorrectly() throws IOException { @Test void parsePreambleAndEntryWithoutNewLine() throws IOException { ParserResult result = parser - .parse(new StringReader("@preamble{some text and \\latex}@article{test,author = {H\'{e}lne Fiaux}}")); + .parse(new StringReader("@preamble{some text and \\latex}@article{test,author = {H'{e}lne Fiaux}}")); Collection parsedEntries = result.getDatabase().getEntries(); BibEntry parsedEntry = parsedEntries.iterator().next(); @@ -1168,7 +1168,7 @@ void parsePreambleAndEntryWithoutNewLine() throws IOException { assertEquals(1, parsedEntries.size()); assertEquals(StandardEntryType.Article, parsedEntry.getType()); assertEquals(Optional.of("test"), parsedEntry.getCiteKeyOptional()); - assertEquals(Optional.of("H\'{e}lne Fiaux"), parsedEntry.getField(StandardField.AUTHOR)); + assertEquals(Optional.of("H'{e}lne Fiaux"), parsedEntry.getField(StandardField.AUTHOR)); } @Test From deedb2c102e88884c7293fc69ed9d1bc737a679b Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 25 Jan 2020 17:25:11 +0100 Subject: [PATCH 2/3] Add missing localization --- src/main/resources/l10n/JabRef_en.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 2659e0a5800..38557bdc52a 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2103,3 +2103,4 @@ Normalize\ newline\ characters=Normalize newline characters Normalizes\ all\ newline\ characters\ in\ the\ field\ content.=Normalizes all newline characters in the field content. Index=Index +Escape=ampersands=Escape ampersands From a96aa702291814cd4fdf341d2c2ecccea0fabc68 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sat, 25 Jan 2020 17:38:58 +0100 Subject: [PATCH 3/3] Update JabRef_en.properties --- src/main/resources/l10n/JabRef_en.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 38557bdc52a..a74b6c18071 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2103,4 +2103,4 @@ Normalize\ newline\ characters=Normalize newline characters Normalizes\ all\ newline\ characters\ in\ the\ field\ content.=Normalizes all newline characters in the field content. Index=Index -Escape=ampersands=Escape ampersands +Escape\ ampersands=Escape ampersands