Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 12 additions & 1 deletion .github/workflows/tests-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ jobs:
run: |
echo "cache_key=jbang-$(date +%F)" >> $GITHUB_OUTPUT
- name: Use cache
if: steps.changed-jablib-files.outputs.any_changed != 'true'
uses: actions/cache@v4
with:
path: ~/.jbang
Expand Down Expand Up @@ -515,6 +516,7 @@ jobs:
with:
files: |
.jbang/*.java
jabkit/src/main/java/**/*.java
jablib/src/main/java/**/*.java
jablib-examples/**/*.java
files_ignore: |
Expand Down Expand Up @@ -546,7 +548,16 @@ jobs:
# We modify the JBang scripts directly to avoid issues with relative paths
for f in ${{ steps.changed-jablib-files.outputs.all_changed_files }}; do
case "$f" in
jablib-examples/*) continue ;; # skip scripts
jablib-examples/*)
# skip scripts
continue
;;
jabkit/*)
# only JabKit needs its modified sources
if [ "${{ matrix.script }}" != ".jbang/JabKitLauncher.java" ]; then
continue
fi
;;
esac
echo "//SOURCES ../$f" >> "${{ matrix.script }}"
done
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv

- We added "IEEE" as another option for parsing plain text citations. [#14233](github.com/JabRef/jabref/pull/14233)
- We added automatic date-based groups that create year/month/day subgroups from an entry’s date fields. [#10822](https://github.com/JabRef/jabref/issues/10822)
- We added `doi-to-bibtex` to `JabKit`. [#14244](https://github.com/JabRef/jabref/pull/14244)

### Changed

Expand Down
4 changes: 3 additions & 1 deletion jabkit/src/main/java/org/jabref/JabKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.jabref.logic.util.Directories;
import org.jabref.logic.util.strings.StringUtil;
import org.jabref.model.entry.BibEntryTypesManager;
import org.jabref.model.entry.identifier.DOI;
import org.jabref.model.util.DummyFileUpdateMonitor;
import org.jabref.model.util.FileUpdateMonitor;

Expand Down Expand Up @@ -72,7 +73,8 @@ public static void main(String[] args) {
Injector.setModelOrService(BibEntryTypesManager.class, entryTypesManager);

ArgumentProcessor argumentProcessor = new ArgumentProcessor(preferences, entryTypesManager);
CommandLine commandLine = new CommandLine(argumentProcessor);
CommandLine commandLine = new CommandLine(argumentProcessor)
.registerConverter(DOI.class, DOI::new);
String usageHeader = BuildInfo.JABREF_BANNER.formatted(buildInfo.version) + "\n" + JABKIT_BRAND;
commandLine.getCommandSpec().usageMessage().header(usageHeader);
applyUsageFooters(commandLine,
Expand Down
1 change: 1 addition & 0 deletions jabkit/src/main/java/org/jabref/cli/ArgumentProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
CheckConsistency.class,
CheckIntegrity.class,
Convert.class,
DoiToBibtex.class,
Fetch.class,
GenerateBibFromAux.class,
GenerateCitationKeys.class,
Expand Down
68 changes: 68 additions & 0 deletions jabkit/src/main/java/org/jabref/cli/DoiToBibtex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.jabref.cli;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;

import org.jabref.logic.exporter.BibDatabaseWriter;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.fetcher.CrossRef;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.identifier.DOI;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;

@Command(name = "doi-to-bibtex", description = "Converts a DOI to BibTeX")
public class DoiToBibtex implements Callable<Integer> {

private static final Logger LOGGER = LoggerFactory.getLogger(DoiToBibtex.class);

@CommandLine.ParentCommand
private ArgumentProcessor argumentProcessor;

@Parameters(paramLabel = "DOI", description = "one or more DOIs to fetch", arity = "1..*")
private DOI[] dois;

@Override
public Integer call() {
var fetcher = new CrossRef();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var fetcher = new CrossRef();
CrossRef fetcher = new CrossRef();

List<BibEntry> entries = new ArrayList<>(dois.length);

for (DOI doi : dois) {
Optional<BibEntry> entry;
try {
entry = fetcher.performSearchById(doi.asString());
} catch (FetcherException e) {
LOGGER.error("Could not fetch DOI from BibTeX", e);
continue;
}

if (entry.isEmpty()) {
LOGGER.error("Could not fetch DOI from BibTeX");
continue;
}

entries.add(entry.get());
}

try (var writer = new OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
var context = new BibDatabaseContext(new BibDatabase(entries));
var bibWriter = new BibDatabaseWriter(writer, context, argumentProcessor.cliPreferences);
Comment on lines +58 to +60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
try (var writer = new OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
var context = new BibDatabaseContext(new BibDatabase(entries));
var bibWriter = new BibDatabaseWriter(writer, context, argumentProcessor.cliPreferences);
try (OutputStreamWriter writer = new OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(entries));
BibDatabaseWriter bibWriter = new BibDatabaseWriter(writer, context, argumentProcessor.cliPreferences);

bibWriter.writeDatabase(context);
} catch (IOException e) {
LOGGER.error("Could not write BibTeX", e);
return 1;
}
return 0;
}
}
34 changes: 34 additions & 0 deletions jablib-examples/doi_to_bibtex.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
///usr/bin/env jbang "$0" "$@" ; exit $?

import org.jabref.logic.exporter.BibWriter;
import org.jabref.logic.exporter.BibDatabaseWriter;
import org.jabref.logic.importer.fetcher.CrossRef;
import org.jabref.logic.preferences.JabRefCliPreferences;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;

import org.tinylog.Logger;

//DESCRIPTION Converts a DOI to BibTeX

//JAVA 25+
//RUNTIME_OPTIONS --enable-native-access=ALL-UNNAMED
//FILES tinylog.properties=tinylog.properties

//DEPS org.jabref:jablib:6.0-SNAPSHOT
//REPOS mavencentral,mavencentralsnapshots=https://central.sonatype.com/repository/maven-snapshots/,s01oss=https://s01.oss.sonatype.org/content/repositories/snapshots/,oss=https://oss.sonatype.org/content/repositories,jitpack=https://jitpack.io,oss2=https://oss.sonatype.org/content/groups/public,ossrh=https://oss.sonatype.org/content/repositories/snapshots,raw=https://raw.githubusercontent.com/JabRef/jabref/refs/heads/main/jablib/lib/

void main() throws Exception {
var preferences = JabRefCliPreferences.getInstance();

// All `IdParserFetcher<DOI>` can do. In JabRef, there is currently only one implemented

var fetcher = new CrossRef();
var entry = fetcher.performSearchById("10.47397/tb/44-3/tb138kopp-jabref").get(); // will throw an exception if not found

try (var writer = new OutputStreamWriter(System.out, StandardCharsets.UTF_8)) {
var context = new BibDatabaseContext(new BibDatabase(List.of(entry)));
var bibWriter = new BibDatabaseWriter(writer, context, preferences);
bibWriter.writeDatabase(context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.jabref.logic.cleanup.FieldFormatterCleanups;
import org.jabref.logic.cleanup.NormalizeWhitespacesCleanup;
import org.jabref.logic.formatter.bibtexfields.TrimWhitespaceFormatter;
import org.jabref.logic.preferences.JabRefCliPreferences;
import org.jabref.logic.preferences.CliPreferences;
import org.jabref.logic.util.strings.StringUtil;
import org.jabref.model.FieldChange;
import org.jabref.model.database.BibDatabase;
Expand Down Expand Up @@ -95,7 +95,7 @@ public BibDatabaseWriter(@NonNull BibWriter bibWriter,
/// @param preferences - used to read all the preferences
public BibDatabaseWriter(@NonNull Writer writer,
@NonNull BibDatabaseContext bibDatabaseContext,
@NonNull JabRefCliPreferences preferences) {
@NonNull CliPreferences preferences) {
this(new BibWriter(writer, bibDatabaseContext.getDatabase().getNewLineSeparator()),
preferences.getSelfContainedExportConfiguration(),
preferences.getFieldPreferences(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jabref.logic.importer.FetcherException;
import org.jabref.model.entry.BibEntry;
Expand All @@ -19,7 +18,7 @@ default List<BibEntry> parseMultiplePlainCitations(String text) throws FetcherEx
return CitationSplitter.splitCitations(text)
.map(Unchecked.function(this::parsePlainCitation))
.flatMap(Optional::stream)
.collect(Collectors.toList());
.toList();
} catch (UncheckedException e) {
throw (FetcherException) e.getCause();
}
Expand Down