From 11d90a17bda0f4df97403fbe4c0ac2241d47c17c Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 22 Dec 2023 03:25:29 +0100 Subject: [PATCH] Fix Copy cite command should respect preferences (#10707) * Fix Copy cite command should respect preferences Fixes #10615 * add changelog fix checsktyle * Fix CHANGELOG.md * Add missing "citation" to "key" * Add debug message at error in logic in CopyMoreAction * Add fallback if preference could not be parsed * Fix key binding setting * More relaxed parsing * Streamline code in AbstractPushToApplication * Add more test cases for configured citation command * Streamline code for copy action * Update src/main/java/org/jabref/gui/preferences/external/ExternalTabViewModel.java * Fix test --------- Co-authored-by: Oliver Kopp --- CHANGELOG.md | 2 + .../jabref/gui/actions/StandardActions.java | 2 +- .../org/jabref/gui/edit/CopyMoreAction.java | 97 +++++++++---------- .../org/jabref/gui/keyboard/KeyBinding.java | 5 +- .../external/ExternalTabViewModel.java | 8 +- .../gui/push/AbstractPushToApplication.java | 37 +------ .../logic/push/CitationCommandString.java | 34 +++++++ .../ExternalApplicationsPreferences.java | 24 +++-- .../jabref/preferences/JabRefPreferences.java | 24 ++--- src/main/resources/l10n/JabRef_en.properties | 2 +- .../jabref/gui/edit/CopyMoreActionTest.java | 6 ++ .../org/jabref/gui/push/PushToEmacsTest.java | 2 +- .../CitationCommandStringTest.java | 44 +++++++++ 13 files changed, 174 insertions(+), 113 deletions(-) create mode 100644 src/main/java/org/jabref/logic/push/CitationCommandString.java create mode 100644 src/test/java/org/jabref/preferences/CitationCommandStringTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 50053b9c270..606bf9aa981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We upgraded to JavaFX 21.0.1. As a consequence JabRef requires now macOS 11 or later and GTK 3.8 or later on Linux [10627](https://github.com/JabRef/jabref/pull/10627). - A user-specific comment fields is not enabled by default, but can be enabled using the "Add" button. [#10424](https://github.com/JabRef/jabref/issues/10424) - We upgraded to Lucene 9.9 for the fulltext search. The search index will be rebuild. [#10686](https://github.com/JabRef/jabref/pull/10686) +- When using "Copy..." -> "Copy citation key", the delimiter configured at "Push applications" is respected. [#10707](https://github.com/JabRef/jabref/pull/10707) ### Fixed @@ -37,6 +38,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv - We fixed some small inconsistencies in the user interface. [#10507](https://github.com/JabRef/jabref/issues/10507) [#10458](https://github.com/JabRef/jabref/issues/10458) [#10660](https://github.com/JabRef/jabref/issues/10660) - We fixed the issue where the Hayagriva YAML exporter would not include a parent field for the publisher/series. [#10596](https://github.com/JabRef/jabref/issues/10596) - We fixed issues in the external file type dialog w.r.t. duplicate entries in the case of a language switch. [#10271](https://github.com/JabRef/jabref/issues/10271) +- We fixed an issue where the right-click action "Copy cite..." did not respect the configured citation command under "External Programs" -> "[Push Applications](https://docs.jabref.org/cite/pushtoapplications)" [#10615](https://github.com/JabRef/jabref/issues/10615) ### Removed diff --git a/src/main/java/org/jabref/gui/actions/StandardActions.java b/src/main/java/org/jabref/gui/actions/StandardActions.java index eb0c94f866d..b53ecee6cc0 100644 --- a/src/main/java/org/jabref/gui/actions/StandardActions.java +++ b/src/main/java/org/jabref/gui/actions/StandardActions.java @@ -13,7 +13,7 @@ public enum StandardActions implements Action { COPY_MORE(Localization.lang("Copy") + "..."), COPY_TITLE(Localization.lang("Copy title"), KeyBinding.COPY_TITLE), COPY_KEY(Localization.lang("Copy citation key"), KeyBinding.COPY_CITATION_KEY), - COPY_CITE_KEY(Localization.lang("Copy \\cite{citation key}"), KeyBinding.COPY_CITE_CITATION_KEY), + COPY_CITE_KEY(Localization.lang("Copy citation key with configured cite command"), KeyBinding.COPY_CITE_CITATION_KEY), COPY_KEY_AND_TITLE(Localization.lang("Copy citation key and title"), KeyBinding.COPY_CITATION_KEY_AND_TITLE), COPY_KEY_AND_LINK(Localization.lang("Copy citation key and link"), KeyBinding.COPY_CITATION_KEY_AND_LINK), COPY_CITATION_HTML(Localization.lang("Copy citation (html)"), KeyBinding.COPY_PREVIEW), diff --git a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java index 0f9bbe3c103..36a770b4422 100644 --- a/src/main/java/org/jabref/gui/edit/CopyMoreAction.java +++ b/src/main/java/org/jabref/gui/edit/CopyMoreAction.java @@ -3,7 +3,7 @@ import java.io.IOException; import java.io.StringReader; import java.util.List; -import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import org.jabref.gui.ClipBoardManager; @@ -17,7 +17,9 @@ import org.jabref.logic.l10n.Localization; import org.jabref.logic.layout.Layout; import org.jabref.logic.layout.LayoutHelper; +import org.jabref.logic.push.CitationCommandString; import org.jabref.logic.util.OS; +import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.preferences.PreferencesService; @@ -58,13 +60,20 @@ public void execute() { } switch (action) { - case COPY_TITLE -> copyTitle(); - case COPY_KEY -> copyKey(); - case COPY_CITE_KEY -> copyCiteKey(); - case COPY_KEY_AND_TITLE -> copyKeyAndTitle(); - case COPY_KEY_AND_LINK -> copyKeyAndLink(); - case COPY_DOI, COPY_DOI_URL -> copyDoi(); - default -> LOGGER.info("Unknown copy command."); + case COPY_TITLE -> + copyTitle(); + case COPY_KEY -> + copyKey(); + case COPY_CITE_KEY -> + copyCiteKey(); + case COPY_KEY_AND_TITLE -> + copyKeyAndTitle(); + case COPY_KEY_AND_LINK -> + copyKeyAndLink(); + case COPY_DOI, COPY_DOI_URL -> + copyDoi(); + default -> + LOGGER.info("Unknown copy command."); } } @@ -94,47 +103,20 @@ private void copyTitle() { } } - private void copyKey() { - List entries = stateManager.getSelectedEntries(); - - // Collect all non-null keys. - List keys = entries.stream() - .filter(entry -> entry.getCitationKey().isPresent()) - .map(entry -> entry.getCitationKey().get()) - .collect(Collectors.toList()); - - if (keys.isEmpty()) { - dialogService.notify(Localization.lang("None of the selected entries have citation keys.")); - return; - } - - final String copiedKeys = String.join(",", keys); - clipBoardManager.setContent(copiedKeys); - - if (keys.size() == entries.size()) { - // All entries had keys. - dialogService.notify(Localization.lang("Copied '%0' to clipboard.", - JabRefDialogService.shortenDialogMessage(copiedKeys))); - } else { - dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined citation key.", - Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); - } - } - private void copyDoi() { List entries = stateManager.getSelectedEntries(); // Collect all non-null DOI or DOI urls if (action == StandardActions.COPY_DOI_URL) { copyDoiList(entries.stream() - .filter(entry -> entry.getDOI().isPresent()) - .map(entry -> entry.getDOI().get().getURIAsASCIIString()) - .collect(Collectors.toList()), entries.size()); + .filter(entry -> entry.getDOI().isPresent()) + .map(entry -> entry.getDOI().get().getURIAsASCIIString()) + .collect(Collectors.toList()), entries.size()); } else { copyDoiList(entries.stream() - .filter(entry -> entry.getDOI().isPresent()) - .map(entry -> entry.getDOI().get().getDOI()) - .collect(Collectors.toList()), entries.size()); + .filter(entry -> entry.getDOI().isPresent()) + .map(entry -> entry.getDOI().get().getDOI()) + .collect(Collectors.toList()), entries.size()); } } @@ -157,7 +139,7 @@ private void copyDoiList(List dois, int size) { } } - private void copyCiteKey() { + private void doCopyKey(Function, String> mapKeyList) { List entries = stateManager.getSelectedEntries(); // Collect all non-null keys. @@ -171,23 +153,31 @@ private void copyCiteKey() { return; } - String citeCommand = Optional.ofNullable(preferencesService.getExternalApplicationsPreferences().getCiteCommand()) - .filter(cite -> cite.contains("\\")) // must contain \ - .orElse("\\cite"); + String clipBoardContent = mapKeyList.apply(keys); - final String copiedCiteCommand = citeCommand + "{" + String.join(",", keys) + '}'; - clipBoardManager.setContent(copiedCiteCommand); + clipBoardManager.setContent(clipBoardContent); if (keys.size() == entries.size()) { // All entries had keys. dialogService.notify(Localization.lang("Copied '%0' to clipboard.", - JabRefDialogService.shortenDialogMessage(copiedCiteCommand))); + JabRefDialogService.shortenDialogMessage(clipBoardContent))); } else { dialogService.notify(Localization.lang("Warning: %0 out of %1 entries have undefined citation key.", Integer.toString(entries.size() - keys.size()), Integer.toString(entries.size()))); } } + private void copyCiteKey() { + doCopyKey(keys -> { + CitationCommandString citeCommand = preferencesService.getExternalApplicationsPreferences().getCiteCommand(); + return citeCommand.prefix() + String.join(citeCommand.delimiter(), keys) + citeCommand.suffix(); + }); + } + + private void copyKey() { + doCopyKey(keys -> String.join(preferencesService.getExternalApplicationsPreferences().getCiteCommand().delimiter(), keys)); + } + private void copyKeyAndTitle() { List entries = stateManager.getSelectedEntries(); @@ -208,7 +198,9 @@ private void copyKeyAndTitle() { for (BibEntry entry : entries) { if (entry.hasCitationKey()) { entriesWithKeys++; - keyAndTitle.append(layout.doLayout(entry, stateManager.getActiveDatabase().get().getDatabase())); + stateManager.getActiveDatabase() + .map(BibDatabaseContext::getDatabase) + .ifPresent(bibDatabase -> keyAndTitle.append(layout.doLayout(entry, bibDatabase))); } } @@ -242,7 +234,7 @@ private void copyKeyAndLink() { List entriesWithKey = entries.stream() .filter(BibEntry::hasCitationKey) - .collect(Collectors.toList()); + .toList(); if (entriesWithKey.isEmpty()) { dialogService.notify(Localization.lang("None of the selected entries have citation keys.")); @@ -250,7 +242,10 @@ private void copyKeyAndLink() { } for (BibEntry entry : entriesWithKey) { - String key = entry.getCitationKey().get(); + String key = entry.getCitationKey().orElse(""); + if (LOGGER.isDebugEnabled() && key.isEmpty()) { + LOGGER.debug("entry {} had no citation key, but it should have had one", entry); + } String url = entry.getField(StandardField.URL).orElse(""); keyAndLink.append(url.isEmpty() ? key : String.format("%s", url, key)); keyAndLink.append(OS.NEWLINE); diff --git a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java index 5706d55cc7b..506d3fc40e4 100644 --- a/src/main/java/org/jabref/gui/keyboard/KeyBinding.java +++ b/src/main/java/org/jabref/gui/keyboard/KeyBinding.java @@ -32,7 +32,10 @@ public enum KeyBinding { CLOSE("Close dialog", Localization.lang("Close dialog"), "Esc", KeyBindingCategory.VIEW), COPY("Copy", Localization.lang("Copy"), "ctrl+C", KeyBindingCategory.EDIT), COPY_TITLE("Copy title", Localization.lang("Copy title"), "ctrl+shift+alt+T", KeyBindingCategory.EDIT), - COPY_CITE_CITATION_KEY("Copy \\cite{citation key}", Localization.lang("Copy \\cite{citation key}"), "ctrl+K", KeyBindingCategory.EDIT), + + // We migrated from "Copy \\cite{citation key}" to "Copy citation key with configured cite command", therefore we keep the "old string" for backwards comppatibility + COPY_CITE_CITATION_KEY("Copy \\cite{citation key}", Localization.lang("Copy citation key with configured cite command"), "ctrl+K", KeyBindingCategory.EDIT), + COPY_CITATION_KEY("Copy citation key", Localization.lang("Copy citation key"), "ctrl+shift+K", KeyBindingCategory.EDIT), COPY_CITATION_KEY_AND_TITLE("Copy citation key and title", Localization.lang("Copy citation key and title"), "ctrl+shift+alt+K", KeyBindingCategory.EDIT), COPY_CITATION_KEY_AND_LINK("Copy citation key and link", Localization.lang("Copy citation key and link"), "ctrl+alt+K", KeyBindingCategory.EDIT), diff --git a/src/main/java/org/jabref/gui/preferences/external/ExternalTabViewModel.java b/src/main/java/org/jabref/gui/preferences/external/ExternalTabViewModel.java index f8e7f96993c..365b7b694d0 100644 --- a/src/main/java/org/jabref/gui/preferences/external/ExternalTabViewModel.java +++ b/src/main/java/org/jabref/gui/preferences/external/ExternalTabViewModel.java @@ -22,6 +22,7 @@ import org.jabref.gui.push.PushToEmacs; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.push.CitationCommandString; import org.jabref.model.strings.StringUtil; import org.jabref.preferences.ExternalApplicationsPreferences; import org.jabref.preferences.PreferencesService; @@ -97,7 +98,8 @@ public void setValues() { PushToApplications.getApplicationByName(initialPushToApplicationPreferences.getActiveApplicationName(), dialogService, preferences) .orElse(new PushToEmacs(dialogService, preferences))); - citeCommandProperty.setValue(initialExternalApplicationPreferences.getCiteCommand()); + citeCommandProperty.setValue(initialExternalApplicationPreferences.getCiteCommand().toString()); + useCustomTerminalProperty.setValue(initialExternalApplicationPreferences.useCustomTerminal()); customTerminalCommandProperty.setValue(initialExternalApplicationPreferences.getCustomTerminalCommand()); useCustomFileBrowserProperty.setValue(initialExternalApplicationPreferences.useCustomFileBrowser()); @@ -110,7 +112,7 @@ public void storeSettings() { ExternalApplicationsPreferences externalPreferences = preferences.getExternalApplicationsPreferences(); externalPreferences.setEMailSubject(eMailReferenceSubjectProperty.getValue()); externalPreferences.setAutoOpenEmailAttachmentsFolder(autoOpenAttachedFoldersProperty.getValue()); - externalPreferences.setCiteCommand(citeCommandProperty.getValue()); + externalPreferences.setCiteCommand(CitationCommandString.from(citeCommandProperty.getValue())); externalPreferences.setUseCustomTerminal(useCustomTerminalProperty.getValue()); externalPreferences.setCustomTerminalCommand(customTerminalCommandProperty.getValue()); externalPreferences.setUseCustomFileBrowser(useCustomFileBrowserProperty.getValue()); @@ -229,6 +231,6 @@ public StringProperty customFileBrowserCommandProperty() { } public void resetCiteCommandToDefault() { - this.citeCommandProperty.setValue(preferences.getExternalApplicationsPreferences().getDefaultCiteCommand()); + this.citeCommandProperty.setValue(preferences.getExternalApplicationsPreferences().getDefaultCiteCommand().toString()); } } diff --git a/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java b/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java index aa84c74d3e9..3de3e190432 100644 --- a/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java +++ b/src/main/java/org/jabref/gui/push/AbstractPushToApplication.java @@ -26,9 +26,6 @@ public abstract class AbstractPushToApplication implements PushToApplication { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPushToApplication.class); - private static final String CITE_KEY1 = "key1"; - private static final String CITE_KEY2 = "key2"; - protected boolean couldNotCall; // Set to true in case the command could not be executed, e.g., if the file is not found protected boolean couldNotPush; // Set to true in case the tunnel to the program (if one is used) does not operate protected boolean notDefined; // Set to true if the corresponding path is not defined in the preferences @@ -38,36 +35,11 @@ public abstract class AbstractPushToApplication implements PushToApplication { protected final DialogService dialogService; protected final PreferencesService preferencesService; - private String cachedCiteCommand; - private String cachedCitePrefix; - private String cachedCiteSuffix; - private String cachedCiteDelimiter; - public AbstractPushToApplication(DialogService dialogService, PreferencesService preferencesService) { this.dialogService = dialogService; this.preferencesService = preferencesService; } - private void dissectCiteCommand() { - String preferencesCiteCommand = preferencesService.getExternalApplicationsPreferences().getCiteCommand(); - - if (preferencesCiteCommand != null && preferencesCiteCommand.equals(cachedCiteCommand)) { - return; - } - - cachedCiteCommand = preferencesCiteCommand; - - int indexKey1 = cachedCiteCommand.indexOf(CITE_KEY1); - int indexKey2 = cachedCiteCommand.indexOf(CITE_KEY2); - if (indexKey1 < 0 || indexKey2 < 0 || indexKey2 < (indexKey1 + CITE_KEY1.length())) { - return; - } - - cachedCitePrefix = preferencesCiteCommand.substring(0, indexKey1); - cachedCiteDelimiter = preferencesCiteCommand.substring(preferencesCiteCommand.lastIndexOf(CITE_KEY1) + CITE_KEY1.length(), indexKey2); - cachedCiteSuffix = preferencesCiteCommand.substring(preferencesCiteCommand.lastIndexOf(CITE_KEY2) + CITE_KEY2.length()); - } - @Override public JabRefIcon getApplicationIcon() { return IconTheme.JabRefIcons.APPLICATION_GENERIC; @@ -170,18 +142,15 @@ protected String getCommandName() { } protected String getCitePrefix() { - dissectCiteCommand(); - return cachedCitePrefix; + return preferencesService.getExternalApplicationsPreferences().getCiteCommand().prefix(); } public String getDelimiter() { - dissectCiteCommand(); - return cachedCiteDelimiter; + return preferencesService.getExternalApplicationsPreferences().getCiteCommand().delimiter(); } protected String getCiteSuffix() { - dissectCiteCommand(); - return cachedCiteSuffix; + return preferencesService.getExternalApplicationsPreferences().getCiteCommand().suffix(); } @Override diff --git a/src/main/java/org/jabref/logic/push/CitationCommandString.java b/src/main/java/org/jabref/logic/push/CitationCommandString.java new file mode 100644 index 00000000000..8a645e51fba --- /dev/null +++ b/src/main/java/org/jabref/logic/push/CitationCommandString.java @@ -0,0 +1,34 @@ +package org.jabref.logic.push; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public record CitationCommandString(String prefix, String delimiter, String suffix) { + private static final Logger LOGGER = LoggerFactory.getLogger(CitationCommandString.class); + private static final String CITE_KEY1 = "key1"; + private static final String CITE_KEY2 = "key2"; + + @Override + public String toString() { + return prefix + CITE_KEY1 + delimiter + CITE_KEY2 + suffix; + } + + public static CitationCommandString from(String completeCiteCommand) { + int indexKey1 = completeCiteCommand.indexOf(CITE_KEY1); + int indexKey2 = completeCiteCommand.indexOf(CITE_KEY2); + if (indexKey1 < 0 || indexKey2 < 0 || indexKey2 < (indexKey1 + CITE_KEY1.length())) { + LOGGER.info("Wrong indexes {} {} for completeCiteCommand {}. Using default delimiter and suffix.", indexKey1, indexKey2, completeCiteCommand); + if (completeCiteCommand.isEmpty()) { + completeCiteCommand = "\\cite{"; + } else if (!completeCiteCommand.endsWith("{")) { + completeCiteCommand += "{"; + } + return new CitationCommandString(completeCiteCommand, ",", "}"); + } + + String prefix = completeCiteCommand.substring(0, indexKey1); + String delim = completeCiteCommand.substring(completeCiteCommand.lastIndexOf(CITE_KEY1) + CITE_KEY1.length(), indexKey2); + String suffix = completeCiteCommand.substring(completeCiteCommand.lastIndexOf(CITE_KEY2) + CITE_KEY2.length()); + return new CitationCommandString(prefix, delim, suffix); + } +} diff --git a/src/main/java/org/jabref/preferences/ExternalApplicationsPreferences.java b/src/main/java/org/jabref/preferences/ExternalApplicationsPreferences.java index 45670b68a28..992038c80f3 100644 --- a/src/main/java/org/jabref/preferences/ExternalApplicationsPreferences.java +++ b/src/main/java/org/jabref/preferences/ExternalApplicationsPreferences.java @@ -1,17 +1,21 @@ package org.jabref.preferences; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import org.jabref.logic.push.CitationCommandString; + public class ExternalApplicationsPreferences { private final StringProperty eMailSubject; private final BooleanProperty shouldAutoOpenEmailAttachmentsFolder; - private final StringProperty citeCommand; + private final ObjectProperty citeCommand; - private final StringProperty defaultCiteCommand; + private final ObjectProperty defaultCiteCommand; private final BooleanProperty useCustomTerminal; private final StringProperty customTerminalCommand; @@ -21,8 +25,8 @@ public class ExternalApplicationsPreferences { public ExternalApplicationsPreferences(String eMailSubject, boolean shouldAutoOpenEmailAttachmentsFolder, - String citeCommand, - String defaultCiteCommand, + CitationCommandString citeCommand, + CitationCommandString defaultCiteCommand, boolean useCustomTerminal, String customTerminalCommand, boolean useCustomFileBrowser, @@ -31,8 +35,8 @@ public ExternalApplicationsPreferences(String eMailSubject, this.eMailSubject = new SimpleStringProperty(eMailSubject); this.shouldAutoOpenEmailAttachmentsFolder = new SimpleBooleanProperty(shouldAutoOpenEmailAttachmentsFolder); - this.citeCommand = new SimpleStringProperty(citeCommand); - this.defaultCiteCommand = new SimpleStringProperty(defaultCiteCommand); + this.citeCommand = new SimpleObjectProperty<>(citeCommand); + this.defaultCiteCommand = new SimpleObjectProperty<>(defaultCiteCommand); this.useCustomTerminal = new SimpleBooleanProperty(useCustomTerminal); this.customTerminalCommand = new SimpleStringProperty(customTerminalCommand); this.useCustomFileBrowser = new SimpleBooleanProperty(useCustomFileBrowser); @@ -64,15 +68,15 @@ public void setAutoOpenEmailAttachmentsFolder(boolean shouldAutoOpenEmailAttachm this.shouldAutoOpenEmailAttachmentsFolder.set(shouldAutoOpenEmailAttachmentsFolder); } - public String getCiteCommand() { + public CitationCommandString getCiteCommand() { return citeCommand.get(); } - public StringProperty citeCommandProperty() { + public ObjectProperty citeCommandProperty() { return citeCommand; } - public void setCiteCommand(String citeCommand) { + public void setCiteCommand(CitationCommandString citeCommand) { this.citeCommand.set(citeCommand); } @@ -136,7 +140,7 @@ public void setKindleEmail(String kindleEmail) { this.kindleEmail.set(kindleEmail); } - public String getDefaultCiteCommand() { + public CitationCommandString getDefaultCiteCommand() { return defaultCiteCommand.getValue(); } } diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java index 28070ab4ed7..90c6bd7b87f 100644 --- a/src/main/java/org/jabref/preferences/JabRefPreferences.java +++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java @@ -97,6 +97,7 @@ import org.jabref.logic.preview.PreviewLayout; import org.jabref.logic.protectedterms.ProtectedTermsLoader; import org.jabref.logic.protectedterms.ProtectedTermsPreferences; +import org.jabref.logic.push.CitationCommandString; import org.jabref.logic.remote.RemotePreferences; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.shared.security.Password; @@ -1670,7 +1671,7 @@ public void storeGlobalCitationKeyPattern(GlobalCitationKeyPattern pattern) { || pattern.getDefaultValue().isEmpty()) { put(DEFAULT_CITATION_KEY_PATTERN, ""); } else { - put(DEFAULT_CITATION_KEY_PATTERN, pattern.getDefaultValue().get(0)); + put(DEFAULT_CITATION_KEY_PATTERN, pattern.getDefaultValue().getFirst()); } // Store overridden definitions to Preferences. @@ -1685,7 +1686,7 @@ public void storeGlobalCitationKeyPattern(GlobalCitationKeyPattern pattern) { for (EntryType entryType : pattern.getAllKeys()) { if (!pattern.isDefaultValue(entryType)) { // first entry in the map is the full pattern - preferences.put(entryType.getName(), pattern.getValue(entryType).get(0)); + preferences.put(entryType.getName(), pattern.getValue(entryType).getFirst()); } } } @@ -1810,8 +1811,8 @@ public ExternalApplicationsPreferences getExternalApplicationsPreferences() { externalApplicationsPreferences = new ExternalApplicationsPreferences( get(EMAIL_SUBJECT), getBoolean(OPEN_FOLDERS_OF_ATTACHED_FILES), - get(CITE_COMMAND), - (String) defaults.get(CITE_COMMAND), + CitationCommandString.from(get(CITE_COMMAND)), + CitationCommandString.from((String) defaults.get(CITE_COMMAND)), !getBoolean(USE_DEFAULT_CONSOLE_APPLICATION), // mind the ! get(CONSOLE_COMMAND), !getBoolean(USE_DEFAULT_FILE_BROWSER_APPLICATION), // mind the ! @@ -1823,7 +1824,7 @@ public ExternalApplicationsPreferences getExternalApplicationsPreferences() { EasyBind.listen(externalApplicationsPreferences.autoOpenEmailAttachmentsFolderProperty(), (obs, oldValue, newValue) -> putBoolean(OPEN_FOLDERS_OF_ATTACHED_FILES, newValue)); EasyBind.listen(externalApplicationsPreferences.citeCommandProperty(), - (obs, oldValue, newValue) -> put(CITE_COMMAND, newValue)); + (obs, oldValue, newValue) -> put(CITE_COMMAND, newValue.toString())); EasyBind.listen(externalApplicationsPreferences.useCustomTerminalProperty(), (obs, oldValue, newValue) -> putBoolean(USE_DEFAULT_CONSOLE_APPLICATION, !newValue)); // mind the ! EasyBind.listen(externalApplicationsPreferences.customTerminalCommandProperty(), @@ -1838,6 +1839,7 @@ public ExternalApplicationsPreferences getExternalApplicationsPreferences() { return externalApplicationsPreferences; } + //************************************************************************************************************* // Main table and search dialog preferences //************************************************************************************************************* @@ -2283,8 +2285,8 @@ private void storeExportSaveOrder(SaveOrder saveOrder) { long saveOrderCount = saveOrder.getSortCriteria().size(); if (saveOrderCount >= 1) { - put(EXPORT_PRIMARY_SORT_FIELD, saveOrder.getSortCriteria().get(0).field.getName()); - putBoolean(EXPORT_PRIMARY_SORT_DESCENDING, saveOrder.getSortCriteria().get(0).descending); + put(EXPORT_PRIMARY_SORT_FIELD, saveOrder.getSortCriteria().getFirst().field.getName()); + putBoolean(EXPORT_PRIMARY_SORT_DESCENDING, saveOrder.getSortCriteria().getFirst().descending); } else { put(EXPORT_PRIMARY_SORT_FIELD, ""); putBoolean(EXPORT_PRIMARY_SORT_DESCENDING, false); @@ -2337,7 +2339,7 @@ private List getCustomExportFormats() { for (String toImport : getSeries(CUSTOM_EXPORT_FORMAT)) { List formatData = convertStringToList(toImport); TemplateExporter format = new TemplateExporter( - formatData.get(EXPORTER_NAME_INDEX), + formatData.getFirst(), formatData.get(EXPORTER_FILENAME_INDEX), formatData.get(EXPORTER_EXTENSION_INDEX), layoutPreferences, @@ -2354,10 +2356,10 @@ private void storeCustomExportFormats(List exporters) { } else { for (int i = 0; i < exporters.size(); i++) { List exporterData = new ArrayList<>(); - exporterData.add(EXPORTER_NAME_INDEX, exporters.get(i).getName()); + exporterData.addFirst(exporters.get(i).getName()); exporterData.add(EXPORTER_FILENAME_INDEX, exporters.get(i).getLayoutFileName()); // Only stores the first extension associated with FileType - exporterData.add(EXPORTER_EXTENSION_INDEX, exporters.get(i).getFileType().getExtensions().get(0)); + exporterData.add(EXPORTER_EXTENSION_INDEX, exporters.get(i).getFileType().getExtensions().getFirst()); putStringList(CUSTOM_EXPORT_FORMAT + i, exporterData); } purgeSeries(CUSTOM_EXPORT_FORMAT, exporters.size()); @@ -2861,7 +2863,7 @@ private Set getCustomImportFormats() { importers.add(new CustomImporter(importerString.get(3), importerString.get(2))); } } catch (Exception e) { - LOGGER.warn("Could not load {} from preferences. Will ignore.", importerString.get(0), e); + LOGGER.warn("Could not load {} from preferences. Will ignore.", importerString.getFirst(), e); } } diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index 019dcfcd8ae..25dde6cd490 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -170,12 +170,12 @@ Copied=Copied Copy=Copy Copy\ title=Copy title -Copy\ \\cite{citation\ key}=Copy \\cite{citation key} Copy\ citation\ (html)=Copy citation (html) Copy\ citation\ (text)=Copy citation (text) Copy\ citation\ key=Copy citation key Copy\ citation\ key\ and\ link=Copy citation key and link Copy\ citation\ key\ and\ title=Copy citation key and title +Copy\ citation\ key\ with\ configured\ cite\ command=Copy citation key with configured cite command Copy\ to\ clipboard=Copy to clipboard diff --git a/src/test/java/org/jabref/gui/edit/CopyMoreActionTest.java b/src/test/java/org/jabref/gui/edit/CopyMoreActionTest.java index d5fe209a3a0..ba3c8465be1 100644 --- a/src/test/java/org/jabref/gui/edit/CopyMoreActionTest.java +++ b/src/test/java/org/jabref/gui/edit/CopyMoreActionTest.java @@ -14,11 +14,13 @@ import org.jabref.gui.actions.StandardActions; import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Localization; +import org.jabref.logic.push.CitationCommandString; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; +import org.jabref.preferences.ExternalApplicationsPreferences; import org.jabref.preferences.PreferencesService; import org.junit.jupiter.api.BeforeEach; @@ -58,6 +60,10 @@ public void setUp() { titles.add(title); keys.add("abc"); dois.add("10.1145/3377811.3380330"); + + ExternalApplicationsPreferences externalApplicationsPreferences = mock(ExternalApplicationsPreferences.class); + when(externalApplicationsPreferences.getCiteCommand()).thenReturn(new CitationCommandString("\\cite{", ",", "}")); + when(preferencesService.getExternalApplicationsPreferences()).thenReturn(externalApplicationsPreferences); } @Test diff --git a/src/test/java/org/jabref/gui/push/PushToEmacsTest.java b/src/test/java/org/jabref/gui/push/PushToEmacsTest.java index 830cfff46b5..7e298a2ec6e 100644 --- a/src/test/java/org/jabref/gui/push/PushToEmacsTest.java +++ b/src/test/java/org/jabref/gui/push/PushToEmacsTest.java @@ -41,7 +41,7 @@ public void setup() { when(preferencesService.getPushToApplicationPreferences()).thenReturn(pushToApplicationPreferences); ExternalApplicationsPreferences externalApplicationsPreferences = mock(ExternalApplicationsPreferences.class); - when(externalApplicationsPreferences.getCiteCommand()).thenReturn("\\cite{key1,key2}"); + when(externalApplicationsPreferences.getCiteCommand().toString()).thenReturn("\\cite{key1,key2}"); when(preferencesService.getExternalApplicationsPreferences()).thenReturn(externalApplicationsPreferences); pushToEmacs = new PushToEmacs(dialogService, preferencesService); diff --git a/src/test/java/org/jabref/preferences/CitationCommandStringTest.java b/src/test/java/org/jabref/preferences/CitationCommandStringTest.java new file mode 100644 index 00000000000..0bca17e7eed --- /dev/null +++ b/src/test/java/org/jabref/preferences/CitationCommandStringTest.java @@ -0,0 +1,44 @@ +package org.jabref.preferences; + +import java.util.stream.Stream; + +import org.jabref.logic.push.CitationCommandString; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class CitationCommandStringTest { + + @Test + void testToString() { + assertEquals("\\cite{key1,key2}", new CitationCommandString("\\cite{", ",", "}").toString()); + } + + public static Stream from() { + return Stream.of( + Arguments.of( + new CitationCommandString("\\cite{", ",", "}"), + "\\cite{key1,key2}" + ), + Arguments.of( + new CitationCommandString("\\cite{", ",", "}"), + "\\cite" + ), + // We could do better, but this is very seldom + Arguments.of( + new CitationCommandString("\\cite[key1,key]{", ",", "}"), + "\\cite[key1,key]" + ) + ); + } + + @ParameterizedTest + @MethodSource + void from(CitationCommandString expected, String input) { + assertEquals(expected, CitationCommandString.from(input)); + } +}