Skip to content

Commit

Permalink
Open "near-by" .bib file (#12172)
Browse files Browse the repository at this point in the history
* Fix JavaDoc

* Add opening of a "near-by" .bib file

* Reword CHANGELOG.md

* Rewrite firstBibFile()

Co-authored-by: Ruslan <[email protected]>

* Refine code

Co-authored-by: Ruslan <[email protected]>

* Fix modifiable list

* Add support for Linux

Co-authored-by: Ruslan <[email protected]>

* Change log level

* Refine logic

---------

Co-authored-by: Ruslan <[email protected]>
  • Loading branch information
koppor and InAnYan authored Nov 13, 2024
1 parent bfaec9b commit 5f1dd59
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We added an importer for SSRN URLs. [#12021](https://github.com/JabRef/jabref/pull/12021)
- We added a compare button to the duplicates in the citation relations tab to open the "Possible duplicate entries" window. [#11192](https://github.com/JabRef/jabref/issues/11192)
- We added automatic browser extension install on Windows for Chrome and Edge. [#6076](https://github.com/JabRef/jabref/issues/6076)
- We added support to automatically open a `.bib` file in the current/parent folder if no other library is opened. [koppor#377](https://github.com/koppor/jabref/issues/377)
- We added a search bar for filtering keyboard shortcuts. [#11686](https://github.com/JabRef/jabref/issues/11686)
- By double clicking on a local citation in the Citation Relations Tab you can now jump the linked entry. [#11955](https://github.com/JabRef/jabref/pull/11955)
- We use the menu icon for background tasks as a progress indicator to visualise an import's progress when dragging and dropping several PDF files into the main table. [#12072](https://github.com/JabRef/jabref/pull/12072)
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/cli/ArgumentProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public ArgumentProcessor(String[] args,
}

/**
* Will open a file (like {@link #importFile(String)}, but will also request JabRef to focus on this database.
* Will open a file (like {@link #importFile(String)}, but will also request JabRef to focus on this library.
*
* @return ParserResult with setToOpenTab(true)
*/
Expand Down
89 changes: 89 additions & 0 deletions src/main/java/org/jabref/gui/frame/JabRefFrameViewModel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.jabref.gui.frame;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.SQLException;
import java.util.ArrayList;
Expand Down Expand Up @@ -30,18 +33,22 @@
import org.jabref.logic.UiCommand;
import org.jabref.logic.ai.AiService;
import org.jabref.logic.importer.ImportCleanup;
import org.jabref.logic.importer.OpenDatabase;
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.os.OS;
import org.jabref.logic.shared.DatabaseNotSupportedException;
import org.jabref.logic.shared.exception.InvalidDBMSConnectionPropertiesException;
import org.jabref.logic.shared.exception.NotASharedDatabaseException;
import org.jabref.logic.util.BackgroundTask;
import org.jabref.logic.util.TaskExecutor;
import org.jabref.logic.util.io.FileUtil;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.util.FileUpdateMonitor;

import org.jooq.lambda.Unchecked;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -146,9 +153,12 @@ public boolean close() {
public void handleUiCommands(List<UiCommand> uiCommands) {
LOGGER.debug("Handling UI commands {}", uiCommands);
if (uiCommands.isEmpty()) {
checkForBibInUpperDir();
return;
}

assert !uiCommands.isEmpty();

// Handle blank workspace
boolean blank = uiCommands.stream().anyMatch(UiCommand.BlankWorkspace.class::isInstance);

Expand Down Expand Up @@ -180,6 +190,85 @@ public void handleUiCommands(List<UiCommand> uiCommands) {
});
}

private void checkForBibInUpperDir() {
// "Open last edited databases" happened before this call
// Moreover, there is not any CLI command (especially, not opening any new tab)
// Thus, we check if there are any tabs open.
if (tabContainer.getLibraryTabs().isEmpty()) {
Optional<Path> firstBibFile = firstBibFile();
if (firstBibFile.isPresent()) {
ParserResult parserResult;
try {
parserResult = OpenDatabase.loadDatabase(
firstBibFile.get(),
preferences.getImportFormatPreferences(),
fileUpdateMonitor);
} catch (IOException e) {
LOGGER.error("Could not open bib file {}", firstBibFile.get(), e);
return;
}
List<ParserResult> librariesToOpen = new ArrayList<>(1);
librariesToOpen.add(parserResult);
openDatabases(librariesToOpen);
}
}
}

/// Use case: User starts `JabRef.bat` or `JabRef.exe`. JabRef should open a "close by" bib file.
/// By "close by" a `.bib` file in the current folder or one level up of `JabRef.exe`is meant.
///
/// Paths:
/// - `...\{example-dir}\JabRef\JabRef.exe` (Windows)
/// - `.../{example-dir}/JabRef/bin/JabRef` (Linux)
/// - `...\{example-dir}\JabRef\runtime\bin\JabRef.bat` (Windows)
///
/// In the example, `...\{example-dir}\example.bib` should be found.
///
/// We do NOT go up another level (i.e., everything in `...` is not found)
private Optional<Path> firstBibFile() {
Path absolutePath = Path.of(".").toAbsolutePath();
if (OS.LINUX && absolutePath.startsWith("/usr")) {
return Optional.empty();
}
if (OS.OS_X && absolutePath.startsWith("/Applications")) {
return Optional.empty();
}
if (OS.WINDOWS && absolutePath.startsWith("C:\\Program Files")) {
return Optional.empty();
}

boolean isJabRefExe = Files.exists(Path.of("JabRef.exe"));
boolean isJabRefBat = Files.exists(Path.of("JabRef.bat"));
boolean isJabRef = Files.exists(Path.of("JabRef"));

ArrayList<Path> dirsToCheck = new ArrayList<>(2);
dirsToCheck.add(Path.of(""));
if (isJabRefExe) {
dirsToCheck.add(Path.of("../")); // directory above `JabRef.exe` directory
} else if (isJabRefBat) {
dirsToCheck.add(Path.of("../../../")); // directory above `runtime\bin\JabRef.bat`
} else if (isJabRef) {
dirsToCheck.add(Path.of("../..(/")); // directory above `bin/JabRef` directory
}

// We want to check dirsToCheck only, not all subdirs (due to unnecessary disk i/o)
try {
return dirsToCheck.stream()
.map(Path::toAbsolutePath)
.flatMap(Unchecked.function(dir -> Files.list(dir)))
.filter(path -> FileUtil.getFileExtension(path).equals(Optional.of("bib")))
.findFirst();
} catch (UncheckedIOException ex) {
// Could be access denied exception - when this is started from the application directory
// Therefore log level "debug"
LOGGER.debug("Could not check for existing bib file {}", dirsToCheck, ex);
return Optional.empty();
}
}

/// Opens the libraries given in `parserResults`. This list needs to be modifiable, because invalidDatabases are removed.
///
/// @param parserResults A modifiable list of parser results
private void openDatabases(List<ParserResult> parserResults) {
final List<ParserResult> toOpenTab = new ArrayList<>();

Expand Down

0 comments on commit 5f1dd59

Please sign in to comment.