diff --git a/CHANGELOG.md b/CHANGELOG.md index 936d1cab994..76e1d0e6cb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We removed the alphabetical ordering of the custom tabs and updated the error message when trying to create a general field with a name containing an illegal character. [#5019](https://github.com/JabRef/jabref/issues/5019) - 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) ### Fixed diff --git a/src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java b/src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java index 9809e926cc8..e1201924722 100644 --- a/src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java +++ b/src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java @@ -45,7 +45,8 @@ public static FieldEditorFX getForField(final String fieldName, databaseContext, preferences.getFilePreferences(), journalAbbreviationRepository, - preferences.getBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY)); + preferences.getBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY), + preferences.getBoolean(JabRefPreferences.ALLOW_INTEGER_EDITION_BIBTEX)); final boolean isSingleLine = InternalBibtexFields.isSingleLineField(fieldName); diff --git a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java index 4cedba33962..895d109d79b 100644 --- a/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java +++ b/src/main/java/org/jabref/gui/integrity/IntegrityCheckAction.java @@ -45,7 +45,8 @@ public void execute() { Globals.prefs.getFilePreferences(), Globals.prefs.getBibtexKeyPatternPreferences(), Globals.journalAbbreviationLoader.getRepository(Globals.prefs.getJournalAbbreviationPreferences()), - Globals.prefs.getBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY)); + Globals.prefs.getBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY), + Globals.prefs.getBoolean(JabRefPreferences.ALLOW_INTEGER_EDITION_BIBTEX)); Task> task = new Task>() { @Override diff --git a/src/main/java/org/jabref/gui/preferences/GeneralTab.fxml b/src/main/java/org/jabref/gui/preferences/GeneralTab.fxml index 63eb4929140..2329d548776 100644 --- a/src/main/java/org/jabref/gui/preferences/GeneralTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/GeneralTab.fxml @@ -41,6 +41,7 @@ text="%Warn about unresolved duplicates when closing inspection window"/> + diff --git a/src/main/java/org/jabref/gui/preferences/GeneralTabView.java b/src/main/java/org/jabref/gui/preferences/GeneralTabView.java index 3138230d7cd..e657235caa1 100644 --- a/src/main/java/org/jabref/gui/preferences/GeneralTabView.java +++ b/src/main/java/org/jabref/gui/preferences/GeneralTabView.java @@ -36,6 +36,7 @@ public class GeneralTabView extends VBox implements PrefsTab { @FXML private CheckBox inspectionWarningDuplicate; @FXML private CheckBox confirmDelete; @FXML private CheckBox enforceLegalKeys; + @FXML private CheckBox allowIntegerEdition; @FXML private CheckBox memoryStickMode; @FXML private CheckBox collectTelemetry; @FXML private CheckBox showAdvancedHints; @@ -55,7 +56,7 @@ public class GeneralTabView extends VBox implements PrefsTab { private GeneralTabViewModel viewModel; - private ControlsFxVisualizer validationVisualizer = new ControlsFxVisualizer(); + private final ControlsFxVisualizer validationVisualizer = new ControlsFxVisualizer(); public GeneralTabView(JabRefPreferences preferences) { this.preferences = preferences; @@ -79,6 +80,7 @@ public void initialize() { inspectionWarningDuplicate.selectedProperty().bindBidirectional(viewModel.inspectionWarningDuplicateProperty()); confirmDelete.selectedProperty().bindBidirectional(viewModel.confirmDeleteProperty()); enforceLegalKeys.selectedProperty().bindBidirectional(viewModel.enforceLegalKeysProperty()); + allowIntegerEdition.selectedProperty().bindBidirectional(viewModel.allowIntegerEditionProperty()); memoryStickMode.selectedProperty().bindBidirectional(viewModel.memoryStickModeProperty()); collectTelemetry.selectedProperty().bindBidirectional(viewModel.collectTelemetryProperty()); showAdvancedHints.selectedProperty().bindBidirectional(viewModel.showAdvancedHintsProperty()); diff --git a/src/main/java/org/jabref/gui/preferences/GeneralTabViewModel.java b/src/main/java/org/jabref/gui/preferences/GeneralTabViewModel.java index 4b801f54ee3..e53f517a2a2 100644 --- a/src/main/java/org/jabref/gui/preferences/GeneralTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/GeneralTabViewModel.java @@ -38,6 +38,7 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BooleanProperty memoryStickModeProperty = new SimpleBooleanProperty(); private final BooleanProperty collectTelemetryProperty = new SimpleBooleanProperty(); private final BooleanProperty enforceLegalKeysProperty = new SimpleBooleanProperty(); + private final BooleanProperty allowIntegerEditionProperty = new SimpleBooleanProperty(); private final BooleanProperty showAdvancedHintsProperty = new SimpleBooleanProperty(); private final BooleanProperty markOwnerProperty = new SimpleBooleanProperty(); private final StringProperty markOwnerNameProperty = new SimpleStringProperty(""); @@ -95,6 +96,7 @@ public void setValues() { inspectionWarningDuplicateProperty.setValue(preferences.getBoolean(JabRefPreferences.WARN_ABOUT_DUPLICATES_IN_INSPECTION)); confirmDeleteProperty.setValue(preferences.getBoolean(JabRefPreferences.CONFIRM_DELETE)); enforceLegalKeysProperty.setValue(preferences.getBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY)); + allowIntegerEditionProperty.setValue(preferences.getBoolean(JabRefPreferences.ALLOW_INTEGER_EDITION_BIBTEX)); memoryStickModeProperty.setValue(preferences.getBoolean(JabRefPreferences.MEMORY_STICK_MODE)); collectTelemetryProperty.setValue(preferences.shouldCollectTelemetry()); showAdvancedHintsProperty.setValue(preferences.getBoolean(JabRefPreferences.SHOW_ADVANCED_HINTS)); @@ -126,6 +128,7 @@ public void storeSettings() { preferences.putBoolean(JabRefPreferences.WARN_ABOUT_DUPLICATES_IN_INSPECTION, inspectionWarningDuplicateProperty.getValue()); preferences.putBoolean(JabRefPreferences.CONFIRM_DELETE, confirmDeleteProperty.getValue()); preferences.putBoolean(JabRefPreferences.ENFORCE_LEGAL_BIBTEX_KEY, enforceLegalKeysProperty.getValue()); + preferences.putBoolean(JabRefPreferences.ALLOW_INTEGER_EDITION_BIBTEX, allowIntegerEditionProperty.getValue()); if (preferences.getBoolean(JabRefPreferences.MEMORY_STICK_MODE) && !memoryStickModeProperty.getValue()) { dialogService.showInformationDialogAndWait(Localization.lang("Memory stick mode"), Localization.lang("To disable the memory stick mode" @@ -186,6 +189,8 @@ public boolean validateSettings() { public BooleanProperty enforceLegalKeysProperty() { return this.enforceLegalKeysProperty; } + public BooleanProperty allowIntegerEditionProperty() { return this.allowIntegerEditionProperty; } + public BooleanProperty showAdvancedHintsProperty() { return this.showAdvancedHintsProperty; } // Entry owner diff --git a/src/main/java/org/jabref/logic/integrity/EditionChecker.java b/src/main/java/org/jabref/logic/integrity/EditionChecker.java index c382fe7eab1..fe5a0faabe3 100644 --- a/src/main/java/org/jabref/logic/integrity/EditionChecker.java +++ b/src/main/java/org/jabref/logic/integrity/EditionChecker.java @@ -14,13 +14,16 @@ public class EditionChecker implements ValueChecker { private static final Predicate FIRST_LETTER_CAPITALIZED = Pattern.compile("^[A-Z]").asPredicate(); private static final Predicate ONLY_NUMERALS_OR_LITERALS = Pattern.compile("^([0-9]+|[^0-9].+)$") .asPredicate(); + private static final Predicate ONLY_NUMERALS = Pattern.compile("[0-9]+").asPredicate(); private static final String FIRST_EDITION = "1"; private final BibDatabaseContext bibDatabaseContextEdition; + private final boolean allowIntegerEdition; - public EditionChecker(BibDatabaseContext bibDatabaseContext) { + public EditionChecker(BibDatabaseContext bibDatabaseContext, boolean allowIntegerEdition) { this.bibDatabaseContextEdition = Objects.requireNonNull(bibDatabaseContext); + this.allowIntegerEdition = allowIntegerEdition; } /** @@ -49,8 +52,16 @@ public Optional checkValue(String value) { } //BibTeX - if (!bibDatabaseContextEdition.isBiblatexMode() && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { - return Optional.of(Localization.lang("should have the first letter capitalized")); + if (!bibDatabaseContextEdition.isBiblatexMode()) { + if (!allowIntegerEdition) { + if (!FIRST_LETTER_CAPITALIZED.test(value.trim())) { + return Optional.of(Localization.lang("should have the first letter capitalized")); + } + } else { + if (!ONLY_NUMERALS.test(value.trim()) && !FIRST_LETTER_CAPITALIZED.test(value.trim())) { + return Optional.of(Localization.lang("should have the first letter capitalized")); + } + } } return Optional.empty(); diff --git a/src/main/java/org/jabref/logic/integrity/FieldCheckers.java b/src/main/java/org/jabref/logic/integrity/FieldCheckers.java index a5a1bd97d63..ff39b9b40ad 100644 --- a/src/main/java/org/jabref/logic/integrity/FieldCheckers.java +++ b/src/main/java/org/jabref/logic/integrity/FieldCheckers.java @@ -18,11 +18,15 @@ public class FieldCheckers { private final Multimap fieldChecker; - public FieldCheckers(BibDatabaseContext databaseContext, FilePreferences filePreferences, JournalAbbreviationRepository abbreviationRepository, boolean enforceLegalKey) { - fieldChecker = getAllMap(databaseContext, filePreferences, abbreviationRepository, enforceLegalKey); + public FieldCheckers(BibDatabaseContext databaseContext, FilePreferences filePreferences, + JournalAbbreviationRepository abbreviationRepository, + boolean enforceLegalKey, boolean allowIntegerEdition) { + fieldChecker = getAllMap(databaseContext, filePreferences, abbreviationRepository, enforceLegalKey, allowIntegerEdition); } - private static Multimap getAllMap(BibDatabaseContext databaseContext, FilePreferences filePreferences, JournalAbbreviationRepository abbreviationRepository, boolean enforceLegalKey) { + private static Multimap getAllMap(BibDatabaseContext databaseContext, FilePreferences filePreferences, + JournalAbbreviationRepository abbreviationRepository, + boolean enforceLegalKey, boolean allowIntegerEdition) { ArrayListMultimap fieldCheckers = ArrayListMultimap.create(50, 10); for (String field : InternalBibtexFields.getJournalNameFields()) { @@ -38,7 +42,7 @@ private static Multimap getAllMap(BibDatabaseContext datab fieldCheckers.put(FieldName.TITLE, new BracketChecker()); fieldCheckers.put(FieldName.TITLE, new TitleChecker(databaseContext)); fieldCheckers.put(FieldName.DOI, new DOIValidityChecker()); - fieldCheckers.put(FieldName.EDITION, new EditionChecker(databaseContext)); + fieldCheckers.put(FieldName.EDITION, new EditionChecker(databaseContext, allowIntegerEdition)); fieldCheckers.put(FieldName.FILE, new FileChecker(databaseContext, filePreferences)); fieldCheckers.put(FieldName.HOWPUBLISHED, new HowPublishedChecker(databaseContext)); fieldCheckers.put(FieldName.ISBN, new ISBNChecker()); diff --git a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java index 9e534756bce..de3e1789016 100644 --- a/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java +++ b/src/main/java/org/jabref/logic/integrity/IntegrityCheck.java @@ -18,17 +18,20 @@ public class IntegrityCheck { private final BibtexKeyPatternPreferences bibtexKeyPatternPreferences; private final JournalAbbreviationRepository journalAbbreviationRepository; private final boolean enforceLegalKey; + private final boolean allowIntegerEdition; public IntegrityCheck(BibDatabaseContext bibDatabaseContext, FilePreferences filePreferences, BibtexKeyPatternPreferences bibtexKeyPatternPreferences, JournalAbbreviationRepository journalAbbreviationRepository, - boolean enforceLegalKey) { + boolean enforceLegalKey, + boolean allowIntegerEdition) { this.bibDatabaseContext = Objects.requireNonNull(bibDatabaseContext); this.filePreferences = Objects.requireNonNull(filePreferences); this.bibtexKeyPatternPreferences = Objects.requireNonNull(bibtexKeyPatternPreferences); this.journalAbbreviationRepository = Objects.requireNonNull(journalAbbreviationRepository); this.enforceLegalKey = enforceLegalKey; + this.allowIntegerEdition = allowIntegerEdition; } public List checkBibtexDatabase() { @@ -48,7 +51,11 @@ public List checkBibtexEntry(BibEntry entry) { return result; } - FieldCheckers fieldCheckers = new FieldCheckers(bibDatabaseContext, filePreferences, journalAbbreviationRepository, enforceLegalKey); + FieldCheckers fieldCheckers = new FieldCheckers(bibDatabaseContext, + filePreferences, + journalAbbreviationRepository, + enforceLegalKey, + allowIntegerEdition); for (FieldChecker checker : fieldCheckers.getAll()) { result.addAll(checker.check(entry)); } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 0c1ea92ec4e..4a209790519 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -274,6 +274,7 @@ public class JabRefPreferences implements PreferencesService { public static final String KEY_GEN_ALWAYS_ADD_LETTER = "keyGenAlwaysAddLetter"; public static final String KEY_GEN_FIRST_LETTER_A = "keyGenFirstLetterA"; public static final String ENFORCE_LEGAL_BIBTEX_KEY = "enforceLegalBibtexKey"; + public static final String ALLOW_INTEGER_EDITION_BIBTEX = "allowIntegerEditionBibtex"; public static final String LOCAL_AUTO_SAVE = "localAutoSave"; public static final String RUN_AUTOMATIC_FILE_SEARCH = "runAutomaticFileSearch"; public static final String NUMERIC_FIELDS = "numericFields"; @@ -697,6 +698,7 @@ private JabRefPreferences() { defaults.put(RUN_AUTOMATIC_FILE_SEARCH, Boolean.FALSE); defaults.put(LOCAL_AUTO_SAVE, Boolean.FALSE); defaults.put(ENFORCE_LEGAL_BIBTEX_KEY, Boolean.TRUE); + defaults.put(ALLOW_INTEGER_EDITION_BIBTEX, Boolean.FALSE); // Curly brackets ({}) are the default delimiters, not quotes (") as these cause trouble when they appear within the field value: // Currently, JabRef does not escape them defaults.put(KEY_GEN_FIRST_LETTER_A, Boolean.TRUE); @@ -1352,6 +1354,11 @@ public Boolean getEnforceLegalKeys() { return getBoolean(ENFORCE_LEGAL_BIBTEX_KEY); } + @Override + public Boolean getAllowIntegerEdition() { + return getBoolean(ALLOW_INTEGER_EDITION_BIBTEX); + } + @Override public void updateEntryEditorTabList() { tabList = EntryEditorTabList.create(this); diff --git a/src/main/java/org/jabref/preferences/PreferencesService.java b/src/main/java/org/jabref/preferences/PreferencesService.java index 02ac64b96c3..d904a0b7ad8 100644 --- a/src/main/java/org/jabref/preferences/PreferencesService.java +++ b/src/main/java/org/jabref/preferences/PreferencesService.java @@ -35,9 +35,9 @@ public interface PreferencesService { void storeJournalAbbreviationPreferences(JournalAbbreviationPreferences abbreviationsPreferences); FilePreferences getFilePreferences(); - + XmpPreferences getXMPPreferences(); - + AutoLinkPreferences getAutoLinkPreferences(); Path getWorkingDir(); @@ -95,4 +95,6 @@ public interface PreferencesService { void setShouldWarnAboutDuplicatesForImport(boolean value); void saveCustomEntryTypes(); + + public Boolean getAllowIntegerEdition(); } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 21b05a33f66..2d821285d89 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2103,7 +2103,7 @@ Import\ BibTeX=Import BibTeX Import\ preferences\ from\ a\ file=Import preferences from a file Matching=Matching Same\ as\ --import,\ but\ will\ be\ imported\ to\ the\ opened\ tab=Same as --import, but will be imported to the opened tab - +Allow\ integers\ in\ 'edition'\ field\ in\ BibTeX\ mode=Allow integers in 'edition' field in BibTeX mode LaTeX\ references\ search=LaTeX references search LaTeX\ references\ search\ results=LaTeX references search results LaTeX\ files\ directory\:=LaTeX files directory: diff --git a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java index 02bf279d838..ee300df4fab 100644 --- a/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java +++ b/src/test/java/org/jabref/logic/integrity/IntegrityCheckTest.java @@ -77,6 +77,7 @@ void testEditionChecks() { assertCorrect(withMode(createContext("edition", "Third"), BibDatabaseMode.BIBTEX)); assertWrong(withMode(createContext("edition", "second"), BibDatabaseMode.BIBTEX)); assertWrong(withMode(createContext("edition", "2"), BibDatabaseMode.BIBTEX)); + assertCorrect(withMode(createContext("edition", "2"), BibDatabaseMode.BIBTEX), true); assertWrong(withMode(createContext("edition", "2nd"), BibDatabaseMode.BIBTEX)); assertCorrect(withMode(createContext("edition", "2"), BibDatabaseMode.BIBLATEX)); assertCorrect(withMode(createContext("edition", "10"), BibDatabaseMode.BIBLATEX)); @@ -341,7 +342,7 @@ void testEntryIsUnchangedAfterChecks() { new IntegrityCheck(context, mock(FilePreferences.class), createBibtexKeyPatternPreferences(), - new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true) + new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true, false) .checkBibtexDatabase(); assertEquals(clonedEntry, entry); @@ -379,7 +380,17 @@ private void assertWrong(BibDatabaseContext context) { List messages = new IntegrityCheck(context, mock(FilePreferences.class), createBibtexKeyPatternPreferences(), - new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true) + new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true, false) + .checkBibtexDatabase(); + assertFalse(messages.isEmpty(), messages.toString()); + } + + private void assertWrong(BibDatabaseContext context, boolean allowIntegerEdition) { + List messages = new IntegrityCheck(context, + mock(FilePreferences.class), + createBibtexKeyPatternPreferences(), + new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true, + allowIntegerEdition) .checkBibtexDatabase(); assertFalse(messages.isEmpty(), messages.toString()); } @@ -388,7 +399,17 @@ private void assertCorrect(BibDatabaseContext context) { List messages = new IntegrityCheck(context, mock(FilePreferences.class), createBibtexKeyPatternPreferences(), - new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true + new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true, false + ).checkBibtexDatabase(); + assertEquals(Collections.emptyList(), messages); + } + + private void assertCorrect(BibDatabaseContext context, boolean allowIntegerEdition) { + List messages = new IntegrityCheck(context, + mock(FilePreferences.class), + createBibtexKeyPatternPreferences(), + new JournalAbbreviationRepository(new Abbreviation("IEEE Software", "IEEE SW")), true, + allowIntegerEdition ).checkBibtexDatabase(); assertEquals(Collections.emptyList(), messages); }