Skip to content

Commit

Permalink
Add truncate as a BibTex key modifier (#6427)
Browse files Browse the repository at this point in the history
* Add modifier to truncate a BibTex key

* Add tests for the truncate BibTex key modifier

* Revert "Add tests for the truncate BibTex key modifier"

This reverts commit 19fbbb3

The tests were placed in the wrong file.

* Add tests for the truncate bracketed pattern modifier

* Remove unnecessary imports in the test for the truncate bracketed pattern modifier

* Fix code style of local variable

* Refactor BracketedPatternTest to maintain a parallel directory structure

* Refactor test for the truncate BibTex key modifier

* Drop unused and unnecessary imports from BracketedPatternTest.java

* Refactor truncate modifier to be compatible with Formatters

* Fix type in truncate modifier test

* Add check for Null in format

* Refactor tests for truncate modifier

* Add truncation for long directory names

* Fix name and documentation of createDirNameFromPattern

* Update src/main/java/org/jabref/logic/formatter/minifier/TruncateFormatter.java

Co-authored-by: Christoph <cschwentker@gmail.com>

* Fix matching the modifier String to a TruncateFormatter

* Fix encapsulation and naming in TruncateFormatter

* Fix JavaDoc in TruncateFormatter

* Add changes to CHANGELOG.md

* Fix createDirNameFromPattern to verify names of subfolders

* Add tests for long directory names

* Fix truncate with negative integer

* Add test with negative index

* Add test with invalid data

* Refactor names of truncate tests

* Add TruncateFormatter to general Formatter tests

* Fix truncate with negative index

* Drop truncation of long directory names

* Fix mating truncate in Formatters.java

Change to use a precompiled pattern for matching 'truncateN'

* Fix matching `truncateN` in Formatters.java

Change to use a precompiled pattern for matching 'truncateN'

* Resolve conflicts

* Refactor truncate tests in BracketedPatternTest

Co-authored-by: Christoph <cschwentker@gmail.com>
  • Loading branch information
k3KAW8Pnf7mkmdSMPHz27 and Siedlerchr authored May 13, 2020
1 parent 98b62ba commit 16d4938
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We implemented an option to download fulltext files while importing. [#6381](https://github.com/JabRef/jabref/pull/6381)
- We added a progress-indicator showing the average progress of background tasks to the toolbar. Clicking it reveals a pop-over with a list of running background tasks. [6443](https://github.com/JabRef/jabref/pull/6443)
- We fixed the bug when strike the delete key in the text field. [#6421](https://github.com/JabRef/jabref/issues/6421)
- We added a BibTex key modifier for truncating strings. [#3915](https://github.com/JabRef/jabref/issues/3915)
- We added support for jumping to target entry when typing letter/digit after sorting a column in maintable [#6146](https://github.com/JabRef/jabref/issues/6146)

### Changed
Expand Down Expand Up @@ -57,6 +58,8 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We fixed an issue where JabRef switched to discrete graphics under macOS [#5935](https://github.com/JabRef/jabref/issues/5935)
- We fixed an issue where the Preferences entry preview will be unexpected modified leads to Value too long exception [#6198](https://github.com/JabRef/jabref/issues/6198)
- We fixed an issue where custom jstyles for Open/LibreOffice would only be valid if a layout line for the entry type `default` was at the end of the layout section [#6303](https://github.com/JabRef/jabref/issues/6303)
- We fixed an issue where long directory names created from patterns could create an exception. [#3915](https://github.com/JabRef/jabref/issues/3915)

- We fixed an issue where sort on numeric cases was broken. [#6349](https://github.com/JabRef/jabref/issues/6349)
- We fixed an issue where an "Not on FX thread" exception occured when saving on linux [#6453](https://github.com/JabRef/jabref/issues/6453)
- We fixed an issue where the library sort order was lost. [#6091](https://github.com/JabRef/jabref/issues/6091)
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/org/jabref/logic/formatter/Formatters.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

import org.jabref.logic.formatter.bibtexfields.CleanupUrlFormatter;
import org.jabref.logic.formatter.bibtexfields.ClearFormatter;
Expand All @@ -29,10 +30,12 @@
import org.jabref.logic.formatter.casechanger.TitleCaseFormatter;
import org.jabref.logic.formatter.casechanger.UpperCaseFormatter;
import org.jabref.logic.formatter.minifier.MinifyNameListFormatter;
import org.jabref.logic.formatter.minifier.TruncateFormatter;
import org.jabref.logic.layout.format.LatexToUnicodeFormatter;
import org.jabref.model.cleanup.Formatter;

public class Formatters {
private static final Pattern TRUNCATE_PATTERN = Pattern.compile("\\Atruncate\\d+\\z");

private Formatters() {
}
Expand Down Expand Up @@ -102,6 +105,9 @@ public static Optional<Formatter> getFormatterForModifier(String modifier) {
if (modifier.startsWith(RegexFormatter.KEY)) {
String regex = modifier.substring(RegexFormatter.KEY.length());
return Optional.of(new RegexFormatter(regex));
} else if (TRUNCATE_PATTERN.matcher(modifier).matches()) {
int truncateAfter = Integer.parseInt(modifier.substring(8));
return Optional.of(new TruncateFormatter(truncateAfter));
} else {
return getAll().stream().filter(f -> f.getKey().equals(modifier)).findAny();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.jabref.logic.formatter.minifier;

import java.util.Objects;

import org.jabref.logic.l10n.Localization;
import org.jabref.model.cleanup.Formatter;

public class TruncateFormatter extends Formatter {
private final int TRUNCATE_AFTER;
private final String KEY;

/**
* The TruncateFormatter truncates a string after the given index and removes trailing whitespaces.
*
* @param truncateIndex truncate a string after this index.
*/
public TruncateFormatter(final int truncateIndex) {
TRUNCATE_AFTER = (truncateIndex >= 0) ? truncateIndex : Integer.MAX_VALUE;
KEY = "truncate" + TRUNCATE_AFTER;
}

@Override
public String getName() {
return Localization.lang("Truncate");
}

@Override
public String getKey() {
return KEY;
}

/**
* Truncates a string after the given index.
*/
@Override
public String format(final String input) {
Objects.requireNonNull(input);
final int index = Math.min(TRUNCATE_AFTER, input.length());
return input.substring(0, index).stripTrailing();
}

@Override
public String getDescription() {
return Localization.lang("Truncates a string after a given index.");
}

@Override
public String getExampleInput() {
return "Truncate this sentence.";
}
}
15 changes: 8 additions & 7 deletions src/main/java/org/jabref/logic/util/io/FileUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,22 +273,23 @@ public static String createFileNameFromPattern(BibDatabase database, BibEntry en
}

/**
* Determines filename provided by an entry in a database
* Determines directory name provided by an entry in a database
*
* @param database the database, where the entry is located
* @param entry the entry to which the file should be linked to
* @param fileNamePattern the filename pattern
* @return a suggested fileName
* @param entry the entry to which the directory should be linked to
* @param directoryNamePattern the dirname pattern
* @return a suggested dirName
*/
public static String createDirNameFromPattern(BibDatabase database, BibEntry entry, String fileNamePattern) {
String targetName = BracketedPattern.expandBrackets(fileNamePattern, ';', entry, database);
public static String createDirNameFromPattern(BibDatabase database, BibEntry entry, String directoryNamePattern) {
String targetName = BracketedPattern.expandBrackets(directoryNamePattern, ';', entry, database);

if (targetName.isEmpty()) {
targetName = entry.getCiteKeyOptional().orElse("default");
}

// Removes illegal characters from filename
// Removes illegal characters from directory name
targetName = FileNameCleaner.cleanDirectoryName(targetName);

return targetName;
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2241,5 +2241,6 @@ Computer\ software.\ The\ standard\ styles\ will\ treat\ this\ entry\ type\ as\
A\ data\ set\ or\ a\ similar\ collection\ of\ (mostly)\ raw\ data.=A data set or a similar collection of (mostly) raw data.
Display\ count\ of\ items\ in\ group=Display count of items in group
Remove\ the\ following\ characters\:=Remove the following characters:
Truncate=Truncate
Truncates\ a\ string\ after\ a\ given\ index.=Truncates a string after a given index.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jabref.logic.util;
package org.jabref.logic.bibtexkeypattern;

import org.jabref.logic.bibtexkeypattern.BracketedPattern;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.BibtexString;
Expand All @@ -21,7 +20,7 @@ class BracketedPatternTest {
private BibEntry dbentry;

@BeforeEach
void setUp() throws Exception {
void setUp() {
bibentry = new BibEntry();
bibentry.setField(StandardField.AUTHOR, "O. Kitsune");
bibentry.setField(StandardField.YEAR, "2017");
Expand Down Expand Up @@ -253,4 +252,19 @@ void testEmptyBrackets() {
assertEquals("2003-Organization Science",
BracketedPattern.expandBrackets("[year][]-[journal]", ';', dbentry, database));
}

/**
* Test the [:truncate] modifier
*/
@Test
void expandBracketsChainsTwoTruncateModifiers() {
assertEquals("Open",
BracketedPattern.expandBrackets("[fulltitle:truncate6:truncate5]", ';', dbentry, database));
}

@Test
void expandBracketsDoesNotTruncateWithoutAnArgumentToTruncateModifier() {
assertEquals("Open Source Software and the \"Private-Collective\" Innovation Model: Issues for Organization Science",
BracketedPattern.expandBrackets("[fulltitle:truncate]", ';', dbentry, database));
}
}
7 changes: 5 additions & 2 deletions src/test/java/org/jabref/logic/formatter/FormatterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.stream.Stream;

import org.jabref.logic.formatter.casechanger.ProtectTermsFormatter;
import org.jabref.logic.formatter.minifier.TruncateFormatter;
import org.jabref.logic.protectedterms.ProtectedTermsLoader;
import org.jabref.logic.protectedterms.ProtectedTermsPreferences;
import org.jabref.model.cleanup.Formatter;
Expand Down Expand Up @@ -111,10 +112,12 @@ public static Stream<Formatter> getFormatters() {
Formatters.getAll().stream(),
// following formatters are not contained in the list of all formatters, because
// - the IdentityFormatter is not offered to the user,
// - the ProtectTermsFormatter needs more configuration
// - the ProtectTermsFormatter needs more configuration,
// - the TruncateFormatter needs setup,
Stream.of(
new IdentityFormatter(),
new ProtectTermsFormatter(protectedTermsLoader)));
new ProtectTermsFormatter(protectedTermsLoader),
new TruncateFormatter(0)));
// @formatter:on
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.jabref.logic.formatter.minifier;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Tests in addition to the general tests from {@link org.jabref.logic.formatter.FormatterTest}
*/
public class TruncateFormatterTest {
private final String TITLE = "A Title";

@Test
void formatWorksWith0Index() {
TruncateFormatter formatter = new TruncateFormatter(0);
assertEquals("", formatter.format(TITLE));
}

@Test
void formatRemovesTrailingWhitespace() {
TruncateFormatter formatter = new TruncateFormatter(2);
assertEquals("A", formatter.format(TITLE));
}

@Test
void formatKeepsInternalWhitespace() {
TruncateFormatter formatter = new TruncateFormatter(3);
assertEquals("A T", formatter.format(TITLE));
}

@Test
void formatWorksWith9999Length() {
TruncateFormatter formatter = new TruncateFormatter(9999);
assertEquals(TITLE, formatter.format(TITLE));
}

@Test
void formatIgnoresNegativeIndex() {
TruncateFormatter formatter = new TruncateFormatter(-1);
assertEquals(TITLE, formatter.format(TITLE));
}

@Test
void formatWorksWithEmptyString() {
TruncateFormatter formatter = new TruncateFormatter(9999);
assertEquals("", formatter.format(""));
}

@Test
void formatThrowsExceptionNullString() {
TruncateFormatter formatter = new TruncateFormatter(9999);
assertThrows(NullPointerException.class, () -> formatter.format(null));
}
}

0 comments on commit 16d4938

Please sign in to comment.