diff --git a/CHANGELOG.md b/CHANGELOG.md index 97e5f5b920e..1c64e30e43c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv ### Added +- We added the option to enable the language server in the preferences. [#13697](https://github.com/JabRef/jabref/pull/13697) - We introduced an option in Preferences under (under Linked files -> Linked file name conventions) to automatically rename linked files when an entry data changes. [#11316](https://github.com/JabRef/jabref/issues/11316) - We added tooltips (on hover) for 'Library-specific file directory', 'User-specific file directory' and 'LaTeX file directory' fields of the library properties window. [#12269](https://github.com/JabRef/jabref/issues/12269) - A space is now added by default after citations inserted via the Libre/OpenOffice integration. [#13559](https://github.com/JabRef/jabref/issues/13559) diff --git a/jabgui/build.gradle.kts b/jabgui/build.gradle.kts index d8762e73053..2e14ae5af1d 100644 --- a/jabgui/build.gradle.kts +++ b/jabgui/build.gradle.kts @@ -20,11 +20,12 @@ dependencies { // implementation("org.openjfx:javafx-fxml") // implementation("org.openjfx:javafx-graphics") + implementation(project(":jabls")) + implementation(project(":jabsrv")) + implementation("org.openjfx:javafx-swing") implementation("org.openjfx:javafx-web") - implementation(project(":jabsrv")) - implementation("com.pixelduke:fxthemes") // From JavaFX25 onwards diff --git a/jabgui/src/main/java/module-info.java b/jabgui/src/main/java/module-info.java index 5b62ad2acc4..09b87d8b53f 100644 --- a/jabgui/src/main/java/module-info.java +++ b/jabgui/src/main/java/module-info.java @@ -1,6 +1,6 @@ open module org.jabref { requires org.jabref.jablib; - + requires org.jabref.jabls; requires org.jabref.jabsrv; // Swing diff --git a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java index 9e3448c2ac3..47e191d7b80 100644 --- a/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/jabgui/src/main/java/org/jabref/gui/JabRefGUI.java @@ -33,6 +33,7 @@ import org.jabref.gui.util.UiTaskExecutor; import org.jabref.gui.util.WebViewStore; import org.jabref.http.manager.HttpServerManager; +import org.jabref.languageserver.controller.LanguageServerController; import org.jabref.logic.UiCommand; import org.jabref.logic.ai.AiService; import org.jabref.logic.citation.SearchCitationsRelationsService; @@ -86,6 +87,7 @@ public class JabRefGUI extends Application { private static RemoteListenerServerManager remoteListenerServerManager; private static HttpServerManager httpServerManager; + private static LanguageServerController languageServerController; private Stage mainStage; @@ -156,8 +158,9 @@ public void initialize() { Injector.setModelOrService(DirectoryMonitor.class, directoryMonitor); BibEntryTypesManager entryTypesManager = preferences.getCustomEntryTypesRepository(); + JournalAbbreviationRepository journalAbbreviationRepository = JournalAbbreviationLoader.loadRepository(preferences.getJournalAbbreviationPreferences()); Injector.setModelOrService(BibEntryTypesManager.class, entryTypesManager); - Injector.setModelOrService(JournalAbbreviationRepository.class, JournalAbbreviationLoader.loadRepository(preferences.getJournalAbbreviationPreferences())); + Injector.setModelOrService(JournalAbbreviationRepository.class, journalAbbreviationRepository); Injector.setModelOrService(ProtectedTermsLoader.class, new ProtectedTermsLoader(preferences.getProtectedTermsPreferences())); IndexManager.clearOldSearchIndices(); @@ -168,6 +171,9 @@ public void initialize() { JabRefGUI.httpServerManager = new HttpServerManager(); Injector.setModelOrService(HttpServerManager.class, JabRefGUI.httpServerManager); + JabRefGUI.languageServerController = new LanguageServerController(preferences, journalAbbreviationRepository); + Injector.setModelOrService(LanguageServerController.class, JabRefGUI.languageServerController); + JabRefGUI.stateManager = new JabRefGuiStateManager(); Injector.setModelOrService(StateManager.class, stateManager); @@ -424,6 +430,9 @@ public void startBackgroundTasks() { if (remotePreferences.enableHttpServer()) { httpServerManager.start(stateManager, remotePreferences.getHttpServerUri()); } + if (remotePreferences.enableLanguageServer()) { + languageServerController.start(remotePreferences.getLanguageServerPort()); + } } @Override @@ -467,6 +476,12 @@ public void stop() { LOGGER.trace("HttpServerManager shut down"); }); + executor.submit(() -> { + LOGGER.trace("Shutting down language server controller"); + languageServerController.stop(); + LOGGER.trace("LanguageServerController 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 6a63aa72282..50b3023808a 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 @@ -60,6 +60,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; @@ -147,6 +149,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); }); @@ -158,6 +161,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 beb2b7be4e2..04b34be5b60 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,6 +33,7 @@ import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.http.manager.HttpServerManager; +import org.jabref.languageserver.controller.LanguageServerController; import org.jabref.logic.FilePreferences; import org.jabref.logic.LibraryPreferences; import org.jabref.logic.l10n.Language; @@ -112,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; @@ -149,29 +153,22 @@ public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferenc remotePortValidator = new FunctionBasedValidator<>( remotePortProperty, - input -> { - try { - int portNumber = Integer.parseInt(remotePortProperty().getValue()); - return RemoteUtil.isUserPort(portNumber); - } catch (NumberFormatException ex) { - return false; - } - }, + RemoteUtil::isStringUserPort, ValidationMessage.error("%s > %s %n %n %s".formatted( Localization.lang("Network"), Localization.lang("Remote operation"), Localization.lang("You must enter an integer value in the interval 1025-65535")))); + httpPortValidator = new FunctionBasedValidator<>( httpPortProperty, - input -> { - try { - int portNumber = Integer.parseInt(httpPortProperty().getValue()); - return RemoteUtil.isUserPort(portNumber); - } catch (NumberFormatException ex) { - return false; - } - }, + RemoteUtil::isStringUserPort, ValidationMessage.error("%s".formatted(Localization.lang("You must enter an integer value in the interval 1025-65535")))); + + languageServerPortValidator = new FunctionBasedValidator<>( + languageServerPortProperty, + RemoteUtil::isStringUserPort, + ValidationMessage.error(Localization.lang("You must enter an integer value in the interval 1025-65535"))); + this.trustStoreManager = new TrustStoreManager(Path.of(preferences.getSSLPreferences().getTruststorePath())); } @@ -183,6 +180,10 @@ public ValidationStatus httpPortValidationStatus() { return httpPortValidator.getValidationStatus(); } + public ValidationStatus languageServerPortValidationStatus() { + return languageServerPortValidator.getValidationStatus(); + } + @Override public void setValues() { selectedLanguageProperty.setValue(workspacePreferences.getLanguage()); @@ -227,6 +228,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 @@ -300,6 +304,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(); @@ -312,6 +322,17 @@ public void storeSettings() { httpServerManager.stop(); } + LanguageServerController languageServerController = Injector.instantiateModelOrService(LanguageServerController.class); + // stop in all cases, because the port might have changed (or other settings that can't be easily tracked https://github.com/JabRef/jabref/pull/13697#discussion_r2285997003) + languageServerController.stop(); + if (enableLanguageServerProperty.getValue()) { + remotePreferences.setEnableLanguageServer(true); + languageServerController.start(remotePreferences.getLanguageServerPort()); + } else { + remotePreferences.setEnableLanguageServer(false); + languageServerController.stop(); + } + trustStoreManager.flush(); } @@ -335,6 +356,10 @@ public boolean validateSettings() { validator.addValidators(httpPortValidator); } + if (enableLanguageServerProperty.getValue()) { + validator.addValidators(languageServerPortValidator); + } + if (fontOverrideProperty.getValue()) { validator.addValidators(fontSizeValidator); } @@ -477,6 +502,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 d3b67bea682..6a4f71c5a36 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 @@ -89,6 +89,12 @@ +