Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ee50022
change CAYWEntry.java from class to record
palukku Jul 4, 2025
a20d7b2
Merge branch 'JabRef:main' into cayw
palukku Jul 5, 2025
0dcaab6
refactor
palukku Jul 5, 2025
1863499
replace id hash with sharedID
palukku Jul 5, 2025
8dd9c7c
Merge branch 'JabRef:main' into cayw
palukku Jul 6, 2025
0eba897
Merge branch 'JabRef:main' into cayw
palukku Jul 7, 2025
26655cd
Refactor PushToApplications and move the logic part to jablib
palukku Jul 8, 2025
2c66a6d
Merge remote-tracking branch 'origin/cayw' into cayw
palukku Jul 8, 2025
96d79bc
Add Prefix GUI to all gui classes
palukku Jul 8, 2025
02677ef
Merge branch 'JabRef:main' into cayw
palukku Jul 8, 2025
63cf18c
Move Cite Command Preferences from ExternalApplicationsPreferences to…
palukku Jul 8, 2025
7acb3c0
Merge remote-tracking branch 'origin/cayw' into cayw
palukku Jul 8, 2025
a13d704
Merge branch 'JabRef:main' into cayw
palukku Jul 8, 2025
bfe016f
fix wrong changes
palukku Jul 8, 2025
eed07db
Merge remote-tracking branch 'origin/cayw' into cayw
palukku Jul 8, 2025
124abf4
change field name
palukku Jul 8, 2025
7432cd5
checkstyle and rewriterun
palukku Jul 8, 2025
e80d7d7
add private constructor
palukku Jul 8, 2025
d1cb260
refactor
palukku Jul 8, 2025
881b650
use orElseGet instead of orElse
palukku Jul 8, 2025
19792bf
Merge branch 'main' into cayw
palukku Jul 9, 2025
2b2ad7b
Reduce Gui classes by extending the interfaces with default methods
palukku Jul 9, 2025
566ba96
Add methods for error notification routing and update citation comman…
koppor Jul 9, 2025
ba8aa2b
delete
palukku Jul 9, 2025
7372e55
Merge branch 'cayw-2' into cayw
palukku Jul 9, 2025
552206c
rename
palukku Jul 9, 2025
43c632f
Streamline signature for pushEntries
koppor Jul 9, 2025
dc5e8db
Merge branch 'JabRef:main' into cayw
palukku Jul 9, 2025
ec2bc1e
introduce Applications Enum and change CLI PushToApplications factory.
palukku Jul 9, 2025
b78f9b8
Add doc
koppor Jul 9, 2025
12d89f0
refactor
palukku Jul 9, 2025
ce96f31
fix tests
palukku Jul 9, 2025
b25a985
fix tests2
palukku Jul 9, 2025
282325d
Merge branch 'main' into cayw
palukku Jul 9, 2025
13de083
Merge branch 'main' into cayw
palukku Jul 10, 2025
6be78f2
add ability to cayw to push to other applications
palukku Jul 10, 2025
e1a9c52
rename wrong variables
palukku Jul 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import javafx.scene.control.ButtonBase;
import javafx.scene.control.MenuItem;
Expand All @@ -19,7 +18,6 @@
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.BackgroundTask;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.strings.StringUtil;

Expand Down Expand Up @@ -95,26 +93,6 @@ public Action getAction() {
return application.getAction();
}

private static String getKeyString(List<BibEntry> entries, String delimiter) {
StringBuilder result = new StringBuilder();
Optional<String> citeKey;
boolean first = true;
for (BibEntry bes : entries) {
citeKey = bes.getCitationKey();
if (citeKey.isEmpty() || citeKey.get().isEmpty()) {
LOGGER.warn("Should never occur, because we made sure that all entries have keys");
continue;
}
if (first) {
result.append(citeKey.get());
first = false;
} else {
result.append(delimiter).append(citeKey.get());
}
}
return result.toString();
}

@Override
public void execute() {
// If required, check that all entries have citation keys defined:
Expand All @@ -137,7 +115,6 @@ public void execute() {
}

private void pushEntries() {
BibDatabaseContext database = stateManager.getActiveDatabase().orElseThrow(() -> new NullPointerException("Database null"));
application.pushEntries(database, stateManager.getSelectedEntries(), getKeyString(stateManager.getSelectedEntries(), application.getDelimiter()));
application.pushEntries(stateManager.getSelectedEntries());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ public static List<GuiPushToApplication> getAllGUIApplications(DialogService dia
new GuiPushToTexShop(dialogService, preferences),
new GuiPushToVScode(dialogService, preferences)));

return APPLICATIONS;
return Collections.unmodifiableList(APPLICATIONS);
}

/// In case object "preferences" changes for itself, that update won't be propagated. Does not harm as the current callers do not change that reference itself.
public static Optional<GuiPushToApplication> getGUIApplicationByName(String applicationName, DialogService dialogService, PushToApplicationPreferences preferences) {
return getAllGUIApplications(dialogService, preferences).stream()
.filter(application -> application.getDisplayName().equals(applicationName))
.filter(application -> application.getDisplayName().equalsIgnoreCase(applicationName))
.findAny();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jabref.gui.push;

import java.util.List;
import java.util.Map;

import javafx.beans.property.SimpleMapProperty;
Expand All @@ -9,6 +10,7 @@
import org.jabref.gui.DialogService;
import org.jabref.logic.os.OS;
import org.jabref.logic.push.PushToApplicationPreferences;
import org.jabref.model.entry.BibEntry;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
Expand Down Expand Up @@ -42,6 +44,10 @@ void setup() {

@Test
void pushEntries() {
pushToEmacs.pushEntries(null, null, "key1,key2");
pushToEmacs.pushEntries(
List.of(
new BibEntry().withCitationKey("key1"),
new BibEntry().withCitationKey("key2"))
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jabref.gui.push;

import java.util.List;
import java.util.Map;

import javafx.beans.property.SimpleMapProperty;
Expand All @@ -9,6 +10,7 @@
import org.jabref.gui.DialogService;
import org.jabref.logic.push.CitationCommandString;
import org.jabref.logic.push.PushToApplicationPreferences;
import org.jabref.model.entry.BibEntry;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -80,7 +82,7 @@ void pushEntries() {
String testKey = "TestKey";
String[] expectedCommand = new String[] {TEXWORKS_CLIENT_PATH, "--insert-text", testKey};

pushToTeXworks.pushEntries(null, null, testKey, processBuilder);
pushToTeXworks.pushEntries(List.of(new BibEntry().withCitationKey(testKey)), processBuilder);

verify(processBuilder).command(expectedCommand);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
import org.jabref.logic.os.OS;
import org.jabref.logic.protectedterms.ProtectedTermsLoader;
import org.jabref.logic.protectedterms.ProtectedTermsPreferences;
import org.jabref.logic.push.Applications;
import org.jabref.logic.push.CitationCommandString;
import org.jabref.logic.push.PushToApplicationPreferences;
import org.jabref.logic.push.PushToApplications;
import org.jabref.logic.remote.RemotePreferences;
import org.jabref.logic.search.SearchPreferences;
import org.jabref.logic.shared.prefs.SharedDatabasePreferences;
Expand Down Expand Up @@ -793,15 +793,15 @@ public PushToApplicationPreferences getPushToApplicationPreferences() {
Map<String, String> applicationCommands = new HashMap<>();
// getEmptyIsDefault is used to ensure that an installation of a tool leads to the new path (instead of leaving the empty one)
// Reason: empty string is returned by org.jabref.gui.desktop.os.Windows.detectProgramPath if program is not found. That path is stored in the preferences.
applicationCommands.put(PushToApplications.EMACS, getEmptyIsDefault(PUSH_EMACS_PATH));
applicationCommands.put(PushToApplications.LYX, getEmptyIsDefault(PUSH_LYXPIPE));
applicationCommands.put(PushToApplications.TEXMAKER, getEmptyIsDefault(PUSH_TEXMAKER_PATH));
applicationCommands.put(PushToApplications.TEXSTUDIO, getEmptyIsDefault(PUSH_TEXSTUDIO_PATH));
applicationCommands.put(PushToApplications.TEXWORKS, getEmptyIsDefault(PUSH_TEXWORKS_PATH));
applicationCommands.put(PushToApplications.VIM, getEmptyIsDefault(PUSH_VIM));
applicationCommands.put(PushToApplications.WIN_EDT, getEmptyIsDefault(PUSH_WINEDT_PATH));
applicationCommands.put(PushToApplications.SUBLIME_TEXT, getEmptyIsDefault(PUSH_SUBLIME_TEXT_PATH));
applicationCommands.put(PushToApplications.VSCODE, getEmptyIsDefault(PUSH_VSCODE_PATH));
applicationCommands.put(Applications.EMACS.getDisplayName(), getEmptyIsDefault(PUSH_EMACS_PATH));
applicationCommands.put(Applications.LYX.getDisplayName(), getEmptyIsDefault(PUSH_LYXPIPE));
applicationCommands.put(Applications.TEXMAKER.getDisplayName(), getEmptyIsDefault(PUSH_TEXMAKER_PATH));
applicationCommands.put(Applications.TEXSTUDIO.getDisplayName(), getEmptyIsDefault(PUSH_TEXSTUDIO_PATH));
applicationCommands.put(Applications.TEXWORKS.getDisplayName(), getEmptyIsDefault(PUSH_TEXWORKS_PATH));
applicationCommands.put(Applications.VIM.getDisplayName(), getEmptyIsDefault(PUSH_VIM));
applicationCommands.put(Applications.WIN_EDT.getDisplayName(), getEmptyIsDefault(PUSH_WINEDT_PATH));
applicationCommands.put(Applications.SUBLIME_TEXT.getDisplayName(), getEmptyIsDefault(PUSH_SUBLIME_TEXT_PATH));
applicationCommands.put(Applications.VSCODE.getDisplayName(), getEmptyIsDefault(PUSH_VSCODE_PATH));

pushToApplicationPreferences = new PushToApplicationPreferences(
get(PUSH_TO_APPLICATION),
Expand All @@ -824,24 +824,25 @@ public PushToApplicationPreferences getPushToApplicationPreferences() {

private void storePushToApplicationPath(Map<String, String> commandPair) {
commandPair.forEach((key, value) -> {
switch (key) {
case PushToApplications.EMACS ->
// is only for the preferences and therefore is okay to throw NoSuchElementException
switch (Applications.getApplicationByDisplayName(key).get()) {
case Applications.EMACS ->
put(PUSH_EMACS_PATH, value);
case PushToApplications.LYX ->
case Applications.LYX ->
put(PUSH_LYXPIPE, value);
case PushToApplications.TEXMAKER ->
case Applications.TEXMAKER ->
put(PUSH_TEXMAKER_PATH, value);
case PushToApplications.TEXSTUDIO ->
case Applications.TEXSTUDIO ->
put(PUSH_TEXSTUDIO_PATH, value);
case PushToApplications.TEXWORKS ->
case Applications.TEXWORKS ->
put(PUSH_TEXWORKS_PATH, value);
case PushToApplications.VIM ->
case Applications.VIM ->
put(PUSH_VIM, value);
case PushToApplications.WIN_EDT ->
case Applications.WIN_EDT ->
put(PUSH_WINEDT_PATH, value);
case PushToApplications.SUBLIME_TEXT ->
case Applications.SUBLIME_TEXT ->
put(PUSH_SUBLIME_TEXT_PATH, value);
case PushToApplications.VSCODE ->
case Applications.VSCODE ->
put(PUSH_VSCODE_PATH, value);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;

import org.jabref.logic.l10n.Localization;
import org.jabref.logic.os.OS;
import org.jabref.logic.util.NotificationService;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.strings.StringUtil;

Expand Down Expand Up @@ -35,13 +35,32 @@ public AbstractPushToApplication(NotificationService notificationService, PushTo
this.preferences = preferences;
}

@Override
public void pushEntries(BibDatabaseContext database, List<BibEntry> entries, String keyString) {
pushEntries(database, entries, keyString, new ProcessBuilder());
protected String getKeyString(List<BibEntry> entries, String delimiter) {
StringBuilder result = new StringBuilder();
Optional<String> citeKey;
boolean first = true;
for (BibEntry bes : entries) {
citeKey = bes.getCitationKey();
if (citeKey.isEmpty() || citeKey.get().isEmpty()) {
LOGGER.warn("Should never occur, because we made sure that all entries have keys");
continue;
}
if (first) {
result.append(citeKey.get());
first = false;
} else {
result.append(delimiter).append(citeKey.get());
}
}
return result.toString();
}

public void pushEntries(List<BibEntry> entries) {
pushEntries(entries, new ProcessBuilder());
}

@VisibleForTesting
public void pushEntries(BibDatabaseContext database, List<BibEntry> entries, String keyString, ProcessBuilder processBuilder) {
public void pushEntries(List<BibEntry> entries, ProcessBuilder processBuilder) {
couldNotPush = false;
couldNotCall = false;
notDefined = false;
Expand All @@ -54,6 +73,8 @@ public void pushEntries(BibDatabaseContext database, List<BibEntry> entries, Str
return;
}

String keyString = this.getKeyString(entries, getDelimiter());

// Execute command
try {
if (OS.OS_X) {
Expand Down
51 changes: 51 additions & 0 deletions jablib/src/main/java/org/jabref/logic/push/Applications.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.jabref.logic.push;

import java.util.Optional;

public enum Applications {

EMACS("emacs", "Emacs"),
LYX("lyx", "LyX/Kile"),
TEXMAKER("texmaker", "Texmaker"),
TEXSTUDIO("texstudio", "TeXstudio"),
TEXWORKS("texworks", "TeXworks"),
VIM("vim", "Vim"),
WIN_EDT("winedt", "WinEdt"),
SUBLIME_TEXT("sublime", "Sublime Text"),
TEXSHOP("texshop", "TeXShop"),
VSCODE("vscode", "VScode");

private final String id;
private final String displayName;

Applications(String id, String displayName) {
this.id = id;
this.displayName = displayName;
}

public static Optional<Applications> getApplicationByDisplayName(String key) {
for (Applications application : Applications.values()) {
if (application.getDisplayName().equalsIgnoreCase(key)) {
return Optional.of(application);
}
}
return Optional.empty();
}

public static Optional<Applications> getApplicationById(String key) {
for (Applications application : Applications.values()) {
if (application.getId().equalsIgnoreCase(key)) {
return Optional.of(application);
}
}
return Optional.empty();
}

public String getId() {
return id;
}

public String getDisplayName() {
return displayName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.nio.file.Path;
import java.util.List;

import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;

/**
Expand All @@ -23,7 +22,7 @@ public interface PushToApplication {
* The actual operation. This method will not be called on the event dispatch thread, so it should not do GUI
* operations without utilizing invokeLater().
*/
void pushEntries(BibDatabaseContext database, List<BibEntry> entries, String keyString);
void pushEntries(List<BibEntry> entries);

/**
* Reporting etc., this method is called on the event dispatch thread after pushEntries() returns.
Expand Down
55 changes: 15 additions & 40 deletions jablib/src/main/java/org/jabref/logic/push/PushToApplications.java
Original file line number Diff line number Diff line change
@@ -1,53 +1,28 @@
package org.jabref.logic.push;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.jabref.logic.util.NotificationService;

public class PushToApplications {

public static final String EMACS = "Emacs";
public static final String LYX = "LyX/Kile";
public static final String TEXMAKER = "Texmaker";
public static final String TEXSTUDIO = "TeXstudio";
public static final String TEXWORKS = "TeXworks";
public static final String VIM = "Vim";
public static final String WIN_EDT = "WinEdt";
public static final String SUBLIME_TEXT = "Sublime Text";
public static final String TEXSHOP = "TeXShop";
public static final String VSCODE = "VScode";

private static final List<PushToApplication> APPLICATIONS = new ArrayList<>();

private PushToApplications() {
}

public static List<PushToApplication> getAllApplications(NotificationService notificationService, PushToApplicationPreferences preferences) {
if (!APPLICATIONS.isEmpty()) {
return Collections.unmodifiableList(APPLICATIONS);
}

APPLICATIONS.addAll(List.of(
new PushToEmacs(notificationService, preferences),
new PushToLyx(notificationService, preferences),
new PushToSublimeText(notificationService, preferences),
new PushToTexmaker(notificationService, preferences),
new PushToTeXstudio(notificationService, preferences),
new PushToTeXworks(notificationService, preferences),
new PushToVim(notificationService, preferences),
new PushToWinEdt(notificationService, preferences),
new PushToTexShop(notificationService, preferences),
new PushToVScode(notificationService, preferences)));

return APPLICATIONS;
}

public static Optional<PushToApplication> getApplicationByName(String applicationName, NotificationService notificationService, PushToApplicationPreferences preferences) {
return getAllApplications(notificationService, preferences).stream()
.filter(application -> application.getDisplayName().equals(applicationName))
.findAny();
/// @param applicationId Used by the CLI to select the application to run. Example: `texstudio`
public static Optional<PushToApplication> getApplicationById(String applicationId, NotificationService notificationService, PushToApplicationPreferences preferences) {
return Applications.getApplicationById(applicationId)
.map(application -> switch (application) {
case EMACS -> new PushToEmacs(notificationService, preferences);
case LYX -> new PushToLyx(notificationService, preferences);
case SUBLIME_TEXT -> new PushToSublimeText(notificationService, preferences);
case TEXMAKER -> new PushToTexmaker(notificationService, preferences);
case TEXSTUDIO -> new PushToTeXstudio(notificationService, preferences);
case TEXWORKS -> new PushToTeXworks(notificationService, preferences);
case VIM -> new PushToVim(notificationService, preferences);
case WIN_EDT -> new PushToWinEdt(notificationService, preferences);
case TEXSHOP -> new PushToTexShop(notificationService, preferences);
case VSCODE -> new PushToVScode(notificationService, preferences);
});
}
}
Loading