Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onSave actions discussion #131 #272

Closed
wants to merge 1 commit into from
Closed
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
9 changes: 8 additions & 1 deletion src/main/java/net/sf/jabref/exporter/SaveDatabaseAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
import net.sf.jabref.collab.ChangeScanner;
import net.sf.jabref.gui.worker.CallBack;
import net.sf.jabref.gui.worker.Worker;
import net.sf.jabref.logic.cleanup.AutoFormatter;
import net.sf.jabref.logic.l10n.Encodings;
import net.sf.jabref.logic.l10n.Localization;
import net.sf.jabref.logic.util.io.FileBasedLock;
import net.sf.jabref.model.entry.BibtexEntry;

import javax.swing.*;
import java.io.File;
Expand All @@ -52,7 +54,6 @@ public class SaveDatabaseAction extends AbstractWorker {


public SaveDatabaseAction(BasePanel panel) {

this.panel = panel;
this.frame = panel.frame();
}
Expand Down Expand Up @@ -184,6 +185,12 @@ public void run() {
// lacking keys, before saving:
panel.autoGenerateKeysBeforeSaving();

// onSave cleanup actions
for(BibtexEntry entry: panel.database.getEntries()) {
AutoFormatter formatter = new AutoFormatter(entry);
formatter.runDefaultCleanups();
}

if (!FileBasedLock.waitForFileLock(panel.getFile(), 10)) {
success = false;
fileLockedError = true;
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/net/sf/jabref/logic/cleanup/AutoFormatter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package net.sf.jabref.logic.cleanup;

import net.sf.jabref.model.entry.BibtexEntry;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* This class includes sensible defaults for consistent formatting of BibTex entries.
*/
public class AutoFormatter {
private BibtexEntry entry;

public AutoFormatter(BibtexEntry entry) {
this.entry = entry;
}

/**
* Runs all default cleanups for the BibTex entry.
*/
public void runDefaultCleanups() {
applySuperscripts();
}

/**
* Converts ordinal numbers to superscripts, e.g. 1st, 2nd or 3rd.
* Run the replacement for every available BibTex field.
* Will replace ordinal numbers even if they are semantically wrong, e.g. 21rd
*
* <example>
* 1st Conf. Cloud Computing -> 1\textsuperscript{st} Conf. Cloud Computing
* </example>
*/
public void applySuperscripts() {
// find possible superscripts on word boundaries
final Pattern pattern = Pattern.compile("\\b(\\d+)(st|nd|rd|th)\\b", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
// adds superscript tag
final String replace = "$1\\\\textsuperscript{$2}";

for(String name: entry.getAllFields()) {
String value = entry.getField(name);

// nothing to do
if (value == null || value.isEmpty()) {
continue;
}

Matcher matcher = pattern.matcher(value);
// replace globally
String newValue = matcher.replaceAll(replace);

// write field
if(!newValue.equals(value)) {
entry.setField(name, newValue);
}
}
}
}
112 changes: 112 additions & 0 deletions src/test/java/net/sf/jabref/logic/cleanup/AutoFormatterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package net.sf.jabref.logic.cleanup;

import junit.framework.Assert;
import net.sf.jabref.model.entry.BibtexEntry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class AutoFormatterTest {
private BibtexEntry entry;

@Before
public void setUp() {
entry = new BibtexEntry();
}

@After
public void teardown() {
entry = null;
}

@Test
public void replacesSuperscript() {
entry.setField("field one", "1st");
entry.setField("field two", "2nd");
entry.setField("field three", "3rd");
entry.setField("field four", "4th");
entry.setField("field five", "21th");

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals("1\\textsuperscript{st}", entry.getField("field one"));
Assert.assertEquals("2\\textsuperscript{nd}", entry.getField("field two"));
Assert.assertEquals("3\\textsuperscript{rd}", entry.getField("field three"));
Assert.assertEquals("4\\textsuperscript{th}", entry.getField("field four"));
Assert.assertEquals("21\\textsuperscript{th}", entry.getField("field five"));
}

@Test
public void replacesSuperscriptsInAllFields() {
entry.setField("field_one", "1st");
entry.setField("field_two", "1st");

new AutoFormatter(entry).applySuperscripts();

for(String name: entry.getAllFields()) {
Assert.assertEquals("1\\textsuperscript{st}", entry.getField(name));
}
}

@Test
public void replaceSuperscriptsEmptyFields() {
entry.setField("empty field", "");
entry.setField("null field", null);

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals("", entry.getField("empty field"));
Assert.assertEquals(null, entry.getField("null field"));
}

@Test
public void replaceSuperscriptsIgnoresCase() {
entry.setField("lowercase", "1st");
entry.setField("uppercase", "1ST");
entry.setField("mixedcase", "1sT");

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals("1\\textsuperscript{st}", entry.getField("lowercase"));
Assert.assertEquals("1\\textsuperscript{ST}", entry.getField("uppercase"));
Assert.assertEquals("1\\textsuperscript{sT}", entry.getField("mixedcase"));
}

@Test
public void replaceSuperscriptsInMultilineStrings() {
entry.setField("multiline", "replace on 1st line\nand on 2nd line.");

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals(
"replace on 1\\textsuperscript{st} line\nand on 2\\textsuperscript{nd} line.",
entry.getField("multiline")
);
}

@Test
public void replaceAllSuperscripts() {
entry.setField("multiple", "1st 2nd 3rd 4th");

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals(
"1\\textsuperscript{st} 2\\textsuperscript{nd} 3\\textsuperscript{rd} 4\\textsuperscript{th}",
entry.getField("multiple")
);
}

@Test
public void ignoreSuperscriptsInsideWords() {
entry.setField("word boundaries", "1st 1stword words1st inside1stwords");

new AutoFormatter(entry).applySuperscripts();

Assert.assertEquals(
"1\\textsuperscript{st} 1stword words1st inside1stwords",
entry.getField("word boundaries")
);
}
}