From 2f3d92c916d9a72f7e7b44afdb6f66b8e0fe07ba Mon Sep 17 00:00:00 2001 From: Philip <37398281+palukku@users.noreply.github.com> Date: Thu, 14 Aug 2025 17:37:19 +0200 Subject: [PATCH 01/14] adds https://github.com/palukku/jabref/issues/23 adds https://github.com/palukku/jabref/issues/38 adds https://github.com/palukku/jabref/issues/42 --- jabgui/build.gradle.kts | 1 + jabgui/src/main/java/module-info.java | 1 + .../main/java/org/jabref/gui/JabRefGUI.java | 14 ++++ .../gui/preferences/general/GeneralTab.java | 7 ++ .../general/GeneralTabViewModel.java | 54 ++++++++++++++ .../gui/preferences/general/GeneralTab.fxml | 6 ++ .../preferences/JabRefCliPreferences.java | 10 ++- .../logic/remote/RemotePreferences.java | 35 ++++++++- .../logic/remote/RemotePreferencesTest.java | 2 +- jabls/src/main/java/module-info.java | 2 +- .../BibtexTextDocumentService.java | 74 ++++++++++++++++--- .../jabref/languageserver/LSPLauncher.java | 12 ++- .../manager/LanguageServerManager.java | 46 ++++++++++++ .../manager/LanguageServerThread.java | 49 ++++++++++++ .../languageserver/manager/package-info.java | 2 + jabsrv/src/main/java/module-info.java | 4 - 16 files changed, 295 insertions(+), 24 deletions(-) create mode 100644 jabls/src/main/java/org/jabref/languageserver/manager/LanguageServerManager.java create mode 100644 jabls/src/main/java/org/jabref/languageserver/manager/LanguageServerThread.java create mode 100644 jabls/src/main/java/org/jabref/languageserver/manager/package-info.java diff --git a/jabgui/build.gradle.kts b/jabgui/build.gradle.kts index d8762e73053..b837855f4ff 100644 --- a/jabgui/build.gradle.kts +++ b/jabgui/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation("org.openjfx:javafx-web") implementation(project(":jabsrv")) + implementation(project(":jabls")) implementation("com.pixelduke:fxthemes") diff --git a/jabgui/src/main/java/module-info.java b/jabgui/src/main/java/module-info.java index 5b62ad2acc4..a79dd369c83 100644 --- a/jabgui/src/main/java/module-info.java +++ b/jabgui/src/main/java/module-info.java @@ -2,6 +2,7 @@ requires org.jabref.jablib; requires org.jabref.jabsrv; + requires org.jabref.jabls; // Swing requires java.desktop; diff --git a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java index 348fa9c41b3..aec9ae84d15 100644 --- a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java @@ -32,6 +32,7 @@ import org.jabref.gui.util.UiTaskExecutor; import org.jabref.gui.util.WebViewStore; import org.jabref.http.manager.HttpServerManager; +import org.jabref.languageserver.manager.LanguageServerManager; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; import org.jabref.logic.citation.SearchCitationsRelationsService; @@ -85,6 +86,7 @@ public class JabRefGUI extends Application { private static RemoteListenerServerManager remoteListenerServerManager; private static HttpServerManager httpServerManager; + private static LanguageServerManager languageServerManager; private Stage mainStage; @@ -167,6 +169,9 @@ public void initialize() { JabRefGUI.httpServerManager = new HttpServerManager(); Injector.setModelOrService(HttpServerManager.class, JabRefGUI.httpServerManager); + JabRefGUI.languageServerManager = new LanguageServerManager(); + Injector.setModelOrService(LanguageServerManager.class, JabRefGUI.languageServerManager); + JabRefGUI.stateManager = new JabRefGuiStateManager(); Injector.setModelOrService(StateManager.class, stateManager); @@ -422,6 +427,9 @@ public void startBackgroundTasks() { if (remotePreferences.enableHttpServer()) { httpServerManager.start(stateManager, remotePreferences.getHttpServerUri()); } + if (remotePreferences.enableLanguageServer()) { + languageServerManager.start(preferences, Injector.instantiateModelOrService(JournalAbbreviationRepository.class), remotePreferences.getLanguageServerPort()); + } } @Override @@ -465,6 +473,12 @@ public void stop() { LOGGER.trace("HttpServerManager shut down"); }); + executor.submit(() -> { + LOGGER.trace("Shutting down language server manager"); + languageServerManager.stop(); + LOGGER.trace("LanguageServerManager shut down"); + }); + executor.submit(() -> { LOGGER.trace("Stopping background tasks"); Unirest.shutDown(); diff --git a/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java b/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java index 28a224ba2ca..839e1ba0976 100644 --- a/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java +++ b/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java @@ -59,6 +59,8 @@ public class GeneralTab extends AbstractPreferenceTabView i @FXML private TextField remotePort; @FXML private CheckBox enableHttpServer; @FXML private TextField httpServerPort; + @FXML private CheckBox enableLanguageServer; + @FXML private TextField languageServerPort; @FXML private Button remoteHelp; @Inject private FileUpdateMonitor fileUpdateMonitor; @Inject private BibEntryTypesManager entryTypesManager; @@ -145,6 +147,7 @@ public void initialize() { Platform.runLater(() -> { validationVisualizer.initVisualization(viewModel.remotePortValidationStatus(), remotePort); validationVisualizer.initVisualization(viewModel.httpPortValidationStatus(), httpServerPort); + validationVisualizer.initVisualization(viewModel.languageServerPortValidationStatus(), languageServerPort); validationVisualizer.initVisualization(viewModel.fontSizeValidationStatus(), fontSize); validationVisualizer.initVisualization(viewModel.customPathToThemeValidationStatus(), customThemePath); }); @@ -156,6 +159,10 @@ public void initialize() { enableHttpServer.selectedProperty().bindBidirectional(viewModel.enableHttpServerProperty()); httpServerPort.textProperty().bindBidirectional(viewModel.httpPortProperty()); httpServerPort.disableProperty().bind(enableHttpServer.selectedProperty().not()); + + enableLanguageServer.selectedProperty().bindBidirectional(viewModel.enableLanguageServerProperty()); + languageServerPort.textProperty().bindBidirectional(viewModel.languageServerPortProperty()); + languageServerPort.disableProperty().bind(enableLanguageServer.selectedProperty().not()); } @FXML diff --git a/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java b/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java index fb753d849c8..dd14af1f6f5 100644 --- a/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java +++ b/jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java @@ -33,8 +33,10 @@ import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.http.manager.HttpServerManager; +import org.jabref.languageserver.manager.LanguageServerManager; import org.jabref.logic.FilePreferences; import org.jabref.logic.LibraryPreferences; +import org.jabref.logic.journals.JournalAbbreviationRepository; import org.jabref.logic.l10n.Language; import org.jabref.logic.l10n.Localization; import org.jabref.logic.net.ssl.TrustStoreManager; @@ -111,6 +113,9 @@ public class GeneralTabViewModel implements PreferenceTabViewModel { private final BooleanProperty enableHttpServerProperty = new SimpleBooleanProperty(); private final StringProperty httpPortProperty = new SimpleStringProperty(""); private final Validator httpPortValidator; + private final Validator languageServerPortValidator; + private final BooleanProperty enableLanguageServerProperty = new SimpleBooleanProperty(); + private final StringProperty languageServerPortProperty = new SimpleStringProperty(""); private final TrustStoreManager trustStoreManager; private final FileUpdateMonitor fileUpdateMonitor; @@ -171,6 +176,19 @@ public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferenc } }, ValidationMessage.error("%s".formatted(Localization.lang("You must enter an integer value in the interval 1025-65535")))); + + languageServerPortValidator = new FunctionBasedValidator<>( + languageServerPortProperty, + input -> { + try { + int portNumber = Integer.parseInt(languageServerPortProperty().getValue()); + return RemoteUtil.isUserPort(portNumber); + } catch (NumberFormatException ex) { + return false; + } + }, + ValidationMessage.error("%s".formatted(Localization.lang("You must enter an integer value in the interval 1025-65535")))); + this.trustStoreManager = new TrustStoreManager(Path.of(preferences.getSSLPreferences().getTruststorePath())); } @@ -182,6 +200,10 @@ public ValidationStatus httpPortValidationStatus() { return httpPortValidator.getValidationStatus(); } + public ValidationStatus languageServerPortValidationStatus() { + return languageServerPortValidator.getValidationStatus(); + } + @Override public void setValues() { selectedLanguageProperty.setValue(workspacePreferences.getLanguage()); @@ -225,6 +247,9 @@ public void setValues() { enableHttpServerProperty.setValue(remotePreferences.enableHttpServer()); httpPortProperty.setValue(String.valueOf(remotePreferences.getHttpPort())); + + enableLanguageServerProperty.setValue(remotePreferences.enableLanguageServer()); + languageServerPortProperty.setValue(String.valueOf(remotePreferences.getLanguageServerPort())); } @Override @@ -297,6 +322,12 @@ public void storeSettings() { } }); + getPortAsInt(languageServerPortProperty.getValue()).ifPresent(newPort -> { + if (remotePreferences.isDifferentLanguageServerPort(newPort)) { + remotePreferences.setLanguageServerPort(newPort); + } + }); + HttpServerManager httpServerManager = Injector.instantiateModelOrService(HttpServerManager.class); // stop in all cases, because the port might have changed httpServerManager.stop(); @@ -309,6 +340,17 @@ public void storeSettings() { httpServerManager.stop(); } + LanguageServerManager languageServerManager = Injector.instantiateModelOrService(LanguageServerManager.class); + // stop in all cases, because the port might have changed + languageServerManager.stop(); + if (enableLanguageServerProperty.getValue()) { + remotePreferences.setEnableLanguageServer(true); + languageServerManager.start(preferences, Injector.instantiateModelOrService(JournalAbbreviationRepository.class), remotePreferences.getLanguageServerPort()); + } else { + remotePreferences.setEnableLanguageServer(false); + languageServerManager.stop(); + } + trustStoreManager.flush(); } @@ -332,6 +374,10 @@ public boolean validateSettings() { validator.addValidators(httpPortValidator); } + if (enableLanguageServerProperty.getValue()) { + validator.addValidators(languageServerPortValidator); + } + if (fontOverrideProperty.getValue()) { validator.addValidators(fontSizeValidator); } @@ -470,6 +516,14 @@ public StringProperty httpPortProperty() { return httpPortProperty; } + public BooleanProperty enableLanguageServerProperty() { + return enableLanguageServerProperty; + } + + public StringProperty languageServerPortProperty() { + return languageServerPortProperty; + } + public void openBrowser() { String url = "https://themes.jabref.org"; try { diff --git a/jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml b/jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml index cab859b9ac9..4929d113058 100644 --- a/jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml +++ b/jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml @@ -88,6 +88,12 @@ +