diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca7162119e5..4e29a3dd866 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- If fetched article is already in database, then the entry merge dialog is shown.
- An error message is now displayed if you try to create a group containing the keyword separator or if there is already a group with the same name. [#3075](https://github.com/JabRef/jabref/issues/3075) and [#1495](https://github.com/JabRef/jabref/issues/1495)
- Integrity warnings are now directly displayed in the entry editor.
+- We added the functionality to have `regex` as modifier. [#457](https://github.com/JabRef/jabref/issues/457)
### Fixed
@@ -23,6 +24,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- We readded the undo mechanism for changes in the entry editor [#2973](https://github.com/JabRef/jabref/issues/2973)
- We fixed an issue where assigning an entry via drag and drop to a group caused JabRef to stop/freeze completely [#3036](https://github.com/JabRef/jabref/issues/3036)
- We fixed the shortcut Ctrl+F for the search field.
+- We fixed an issue where `title_case` and `capitalize` modifiers did not work with shorttitle.
- We fixed an issue where the preferences could not be imported without a restart of JabRef [#3064](https://github.com/JabRef/jabref/issues/3064)
- We fixed an issue where DEL, Ctrl+C, Ctrl+V and Ctrl+A in the search field triggered corresponding actions in the main table [#3067](https://github.com/JabRef/jabref/issues/3067)
- We fixed an issue where JabRef freezed when editing an assigned file in the `General`-Tab [#2930, comment](https://github.com/JabRef/jabref/issues/2930#issuecomment-311050976)
diff --git a/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtil.java b/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtil.java
index a9757c22f30..7e1a1c74d72 100644
--- a/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtil.java
+++ b/src/main/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtil.java
@@ -737,7 +737,7 @@ private static String getAddition(int number) {
* Determines "number" words out of the "title" field in the given BibTeX entry
*/
public static String getTitleWords(int number, String title) {
- return keepLettersAndDigitsOnly(getTitleWordsWithSpaces(number, title));
+ return getTitleWordsWithSpaces(number, title);
}
/**
diff --git a/src/main/java/org/jabref/logic/formatter/Formatters.java b/src/main/java/org/jabref/logic/formatter/Formatters.java
index 862f97d65a9..9f682ae5130 100644
--- a/src/main/java/org/jabref/logic/formatter/Formatters.java
+++ b/src/main/java/org/jabref/logic/formatter/Formatters.java
@@ -16,6 +16,7 @@
import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter;
import org.jabref.logic.formatter.bibtexfields.NormalizePagesFormatter;
import org.jabref.logic.formatter.bibtexfields.OrdinalsToSuperscriptFormatter;
+import org.jabref.logic.formatter.bibtexfields.RegexFormatter;
import org.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter;
import org.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter;
import org.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter;
@@ -56,6 +57,7 @@ public class Formatters {
new NormalizeNamesFormatter(),
new NormalizePagesFormatter(),
new OrdinalsToSuperscriptFormatter(),
+ new RegexFormatter(),
new RemoveBracesFormatter(),
new UnitsToLatexFormatter(),
new EscapeUnderscoresFormatter()
@@ -63,12 +65,24 @@ public class Formatters {
public static final List ALL = new ArrayList<>();
+ private static final String REGEX = "regex";
+
+ private static final int LENGTH_OF_REGEX_PREFIX = REGEX.length();
+
private Formatters() {
}
public static Optional getFormatterForModifier(String modifier) {
Objects.requireNonNull(modifier);
- Optional formatter = ALL.stream().filter(f -> f.getKey().equals(modifier)).findAny();
+ Optional formatter;
+
+ if (modifier.matches("regex.*")) {
+ String regex = modifier.substring(LENGTH_OF_REGEX_PREFIX);
+ RegexFormatter.setRegex(regex);
+ formatter = ALL.stream().filter(f -> f.getKey().equals("regex")).findAny();
+ } else {
+ formatter = ALL.stream().filter(f -> f.getKey().equals(modifier)).findAny();
+ }
if (formatter.isPresent()) {
return formatter;
}
diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/RegexFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/RegexFormatter.java
new file mode 100644
index 00000000000..3ad3b763676
--- /dev/null
+++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/RegexFormatter.java
@@ -0,0 +1,105 @@
+package org.jabref.logic.formatter.bibtexfields;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.jabref.logic.l10n.Localization;
+import org.jabref.model.cleanup.Formatter;
+
+public class RegexFormatter implements Formatter {
+
+ private static final Pattern PATTERN_ESCAPED_OPENING_CURLY_BRACE = Pattern.compile("\\\\\\{");
+
+ private static final Pattern PATTERN_ESCAPED_CLOSING_CURLY_BRACE = Pattern.compile("\\\\\\}");
+
+ // RegEx to match {...}
+ // \\ is required to have the { interpreted as character
+ // ? is required to disable the aggressive match
+ private static final Pattern PATTERN_ENCLOSED_IN_CURLY_BRACES = Pattern.compile("(\\{.*?})");
+
+ // Magic arbitrary unicode char, which will never appear in bibtex files
+ private static final String PLACEHOLDER_FOR_PROTECTED_GROUP = Character.toString('\u0A14');
+
+ private static final String PLACEHOLDER_FOR_OPENING_CURLY_BRACE = Character.toString('\u0A15');
+
+ private static final String PLACEHOLDER_FOR_CLOSING_CURLY_BRACE = Character.toString('\u0A16');
+
+ private static final String QUOTE_AND_OPENING_BRACE = "\"(";
+
+ private static final int LENGTH_OF_QUOTE_AND_OPENING_BRACE = QUOTE_AND_OPENING_BRACE.length();
+
+ private static final String CLOSING_BRACE_AND_QUOTE = ")\"";
+
+ private static final int LENGTH_OF_CLOSING_BRACE_AND_QUOTE = CLOSING_BRACE_AND_QUOTE.length();
+
+ // stores the regex set by setRegex
+ private static String[] regex;
+
+ @Override
+ public String getName() {
+ return Localization.lang("regular_expression");
+ }
+
+ @Override
+ public String getKey() {
+ return "regex";
+ }
+
+ private String replaceHonoringProtectedGroups(final String input) {
+ Matcher matcher = PATTERN_ENCLOSED_IN_CURLY_BRACES.matcher(input);
+
+ List replaced = new ArrayList<>();
+ while (matcher.find()) {
+ replaced.add(matcher.group(1));
+ }
+ String workingString = matcher.replaceAll(PLACEHOLDER_FOR_PROTECTED_GROUP);
+ workingString = workingString.replaceAll(RegexFormatter.regex[0], RegexFormatter.regex[1]);
+
+ for (String r : replaced) {
+ workingString = workingString.replaceFirst(PLACEHOLDER_FOR_PROTECTED_GROUP, r);
+ }
+ return workingString;
+ }
+
+ @Override
+ public String format(final String input) {
+ Objects.requireNonNull(input);
+ if (regex == null) {
+ return input;
+ }
+
+ Matcher matcherOpeningCurlyBrace = PATTERN_ESCAPED_OPENING_CURLY_BRACE.matcher(input);
+ final String openingCurlyBraceReplaced = matcherOpeningCurlyBrace.replaceAll(PLACEHOLDER_FOR_OPENING_CURLY_BRACE);
+
+ Matcher matcherClosingCurlyBrace = PATTERN_ESCAPED_CLOSING_CURLY_BRACE.matcher(openingCurlyBraceReplaced);
+ final String closingCurlyBraceReplaced = matcherClosingCurlyBrace.replaceAll(PLACEHOLDER_FOR_CLOSING_CURLY_BRACE);
+
+ final String regexApplied = replaceHonoringProtectedGroups(closingCurlyBraceReplaced);
+
+ return regexApplied
+ .replaceAll(PLACEHOLDER_FOR_OPENING_CURLY_BRACE, "\\\\{")
+ .replaceAll(PLACEHOLDER_FOR_CLOSING_CURLY_BRACE, "\\\\}");
+ }
+
+ @Override
+ public String getDescription() {
+ return Localization.lang("Add a regular expression for the key pattern.");
+ }
+
+ @Override
+ public String getExampleInput() {
+ return "Please replace the spaces";
+ }
+
+ public static void setRegex(String rex) {
+ // formatting is like ("exp1","exp2"), we want to remove (" and ")
+ String rexToSet = rex;
+ rexToSet = rexToSet.substring(LENGTH_OF_QUOTE_AND_OPENING_BRACE, rexToSet.length() - LENGTH_OF_CLOSING_BRACE_AND_QUOTE);
+ String[] parts = rexToSet.split("\",\"");
+ regex = parts;
+ }
+
+}
diff --git a/src/main/java/org/jabref/logic/formatter/casechanger/SentenceCaseFormatter.java b/src/main/java/org/jabref/logic/formatter/casechanger/SentenceCaseFormatter.java
index 91082d76e9e..87342d63b3d 100644
--- a/src/main/java/org/jabref/logic/formatter/casechanger/SentenceCaseFormatter.java
+++ b/src/main/java/org/jabref/logic/formatter/casechanger/SentenceCaseFormatter.java
@@ -16,7 +16,7 @@ public String getKey() {
}
/**
- * Converts the first character of the first word of the given string to upper case (and the remaining characters of the first word to lower case), but does not change anything if word starts with "{"
+ * Converts the first character of the first word of the given string to upper case (and the remaining characters of the first word to lower case) and changes other words to lower case, but does not change anything if word starts with "{"
*/
@Override
public String format(String input) {
diff --git a/src/main/resources/l10n/JabRef_da.properties b/src/main/resources/l10n/JabRef_da.properties
index 6041f99e664..e33a26c6035 100644
--- a/src/main/resources/l10n/JabRef_da.properties
+++ b/src/main/resources/l10n/JabRef_da.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Stien_behøver_ikke_at_være_p
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Tilføj_en_kompileret_Importer-klasse_fra_en_ZIP-fil.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-filen_behøver_ikke_at_være_i_din_classpath.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Tilføj_fra_mappe
diff --git a/src/main/resources/l10n/JabRef_de.properties b/src/main/resources/l10n/JabRef_de.properties
index 8484ed0707e..446009f9fcd 100644
--- a/src/main/resources/l10n/JabRef_de.properties
+++ b/src/main/resources/l10n/JabRef_de.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Das_Verzeichnis_muss_nicht_im_K
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Füge_eine_(kompilierte)_externe_Importer_Klasse_aus_Verzeichnis_hinzu.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Das_Verzeichnis_muss_nicht_im_Klassenpfad_von_JabRef_enthalten_sein.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=Ausgewählte_Einträge_zu_dieser_Gruppe_hinzufügen
Add_from_folder=Aus_Klassenpfad_hinzufügen
diff --git a/src/main/resources/l10n/JabRef_el.properties b/src/main/resources/l10n/JabRef_el.properties
index c720bd96c8d..fcda3898416 100644
--- a/src/main/resources/l10n/JabRef_el.properties
+++ b/src/main/resources/l10n/JabRef_el.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=The_path_need_not_be_on_the_cla
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Προσθήκη_από_φάκελο
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index b11658faa84..4fa4b7aa5ce 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=The_path_need_not_be_on_the_cla
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=Add_a_regular_expression_for_the_key_pattern.
+
Add_selected_entries_to_this_group=Add_selected_entries_to_this_group
Add_from_folder=Add_from_folder
diff --git a/src/main/resources/l10n/JabRef_es.properties b/src/main/resources/l10n/JabRef_es.properties
index 23700baaae2..d728f351ef4 100644
--- a/src/main/resources/l10n/JabRef_es.properties
+++ b/src/main/resources/l10n/JabRef_es.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=La_ruta_no_debe_estar_en_la_cla
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Añadir_una_clase_personalizada_(compilada)_Importer_desde_un_archivo_ZIP.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=El_archivo_ZIP_no_tiene_por_qué_estar_en_la_classpath_de_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=Añadir_entradas_seleccionadas_a_este_grupo
Add_from_folder=Añadir_desde_carpeta
diff --git a/src/main/resources/l10n/JabRef_fa.properties b/src/main/resources/l10n/JabRef_fa.properties
index ba9dc4ea2e1..69d8c4b81d6 100644
--- a/src/main/resources/l10n/JabRef_fa.properties
+++ b/src/main/resources/l10n/JabRef_fa.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=
diff --git a/src/main/resources/l10n/JabRef_fr.properties b/src/main/resources/l10n/JabRef_fr.properties
index 49a05fe0e87..81d389c341e 100644
--- a/src/main/resources/l10n/JabRef_fr.properties
+++ b/src/main/resources/l10n/JabRef_fr.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Le_chemin_n'a_pas_besoin_d'êtr
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Ajouter_une_classe_Importer_personnalisée_(compilée)_à_partir_d'une_archive_ZIP.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=L'archive_ZIP_n'a_pas_besoin_d'être_dans_le_chemin_de_classe_de_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=Ajouter_les_entrées_sélectionnées_à_ce_groupe
Add_from_folder=Ajouter_à_partir_du_répertoire
diff --git a/src/main/resources/l10n/JabRef_in.properties b/src/main/resources/l10n/JabRef_in.properties
index 5790c469301..1421d85a28c 100644
--- a/src/main/resources/l10n/JabRef_in.properties
+++ b/src/main/resources/l10n/JabRef_in.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Lokasi_tidak_harus_pada_lokasi_
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Tambah_suaian_kelas_Importer_dari_arsip_ZIP.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Lokasi_arsip_ZIP_tidak_harus_dalam_lokasi_kelas_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Tambah_dari_folder
diff --git a/src/main/resources/l10n/JabRef_it.properties b/src/main/resources/l10n/JabRef_it.properties
index 8e4e488b70f..44d83d9d210 100644
--- a/src/main/resources/l10n/JabRef_it.properties
+++ b/src/main/resources/l10n/JabRef_it.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Il_percorso_non_deve_necessaria
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Aggiungi_una_classe_Importer_personalizzata_(compilata)_da_un_archivio_ZIP.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=L'archivio_ZIP_non_deve_necessariamente_essere_nel_classpath_di_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=Aggiungi_le_voci_selezionate_a_questo_gruppo
Add_from_folder=Aggiungi_da_una_cartella
diff --git a/src/main/resources/l10n/JabRef_ja.properties b/src/main/resources/l10n/JabRef_ja.properties
index 75e86cd37e3..e1d884fa2ce 100644
--- a/src/main/resources/l10n/JabRef_ja.properties
+++ b/src/main/resources/l10n/JabRef_ja.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=このパスは、JabRefのク
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=(コンパイルした)ユーザー定義ImportFormatクラスをZIP書庫から追加します。
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=このZIP書庫は、JabRefのクラスパスにあるとは限りません。
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=フォルダから追加
diff --git a/src/main/resources/l10n/JabRef_nl.properties b/src/main/resources/l10n/JabRef_nl.properties
index 61faa959492..b1ca0f6dbe2 100644
--- a/src/main/resources/l10n/JabRef_nl.properties
+++ b/src/main/resources/l10n/JabRef_nl.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Het_pad_moet_niet_in_het_classp
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Voeg_een_(gecompileerde)_externe_Importer_klasse_van_een_ZIP-archief_toe.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Het_pad_moet_niet_in_het_classpath_van_JabRef_staan.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Voeg_toe_uit_map
diff --git a/src/main/resources/l10n/JabRef_no.properties b/src/main/resources/l10n/JabRef_no.properties
index 0324a734abc..8282809df9b 100644
--- a/src/main/resources/l10n/JabRef_no.properties
+++ b/src/main/resources/l10n/JabRef_no.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Stien_trenger_ikke_\u00e5_v\u00
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Legg_til_en_(kompilert)_egendefinert_Importer-klasse_fra_en_zip-fil.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-filen_trenger_ikke_\u00e5_v\u00e6re_p\u00e5_JabRefs_classpath.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Legg_til_fra_mappe
diff --git a/src/main/resources/l10n/JabRef_pt_BR.properties b/src/main/resources/l10n/JabRef_pt_BR.properties
index 33ab7ff9e95..669d0c1da67 100644
--- a/src/main/resources/l10n/JabRef_pt_BR.properties
+++ b/src/main/resources/l10n/JabRef_pt_BR.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=O_caminho_não_precisa_estar_no
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Adicionar_uma_classe_Importer_customizada_(compilada)_a_partir_de_um_arquivo_zip.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=O_arquivo_zip_não_precisa_estar_no_classpath_do_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Adicionar_a_partir_de_uma_pasta
diff --git a/src/main/resources/l10n/JabRef_ru.properties b/src/main/resources/l10n/JabRef_ru.properties
index b35ae21e2ee..ef66c1f6d9e 100644
--- a/src/main/resources/l10n/JabRef_ru.properties
+++ b/src/main/resources/l10n/JabRef_ru.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Путь_может_не_сов
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Добавить_(скомпил.)_пользовательский_класс_Importer_из_ZIP-архива.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=ZIP-архив_может_не_совпадать_с_путем_классов_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Добавить_из_папки
diff --git a/src/main/resources/l10n/JabRef_sv.properties b/src/main/resources/l10n/JabRef_sv.properties
index cad1056751e..7a3f81935f6 100644
--- a/src/main/resources/l10n/JabRef_sv.properties
+++ b/src/main/resources/l10n/JabRef_sv.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Lägg_till_en_(kompilerad)_Importer-klass_från_en_zip-fil.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Lägg_till_från_mapp
diff --git a/src/main/resources/l10n/JabRef_tr.properties b/src/main/resources/l10n/JabRef_tr.properties
index 630e76b1a59..159c9b2c096 100644
--- a/src/main/resources/l10n/JabRef_tr.properties
+++ b/src/main/resources/l10n/JabRef_tr.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Yolun_JabRef'in_sınıf_yolunda
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Bir_ZIP_arşivinden_(derlenmiş)_özel_İçeAlmaBiçemi_sınıfı_ekle.
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Yolun_JabRef'in_sınıf_yolunda_olması_gerekmez.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=Seçili_girdileri_bu_gruba_ekle
Add_from_folder=Klasörden_ekle
diff --git a/src/main/resources/l10n/JabRef_vi.properties b/src/main/resources/l10n/JabRef_vi.properties
index 9f960cff6a8..ebfc8efef59 100644
--- a/src/main/resources/l10n/JabRef_vi.properties
+++ b/src/main/resources/l10n/JabRef_vi.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=Đường_dẫn_không_được
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=Thêm_một_lớp_ĐịnhdạngNhập_tùy_biến_(được_biên_dịch)_từ_một_tập_tin-zip._
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=Tập_tin-zip_không_được_trùng_với_đường_dẫn_lớp_của_JabRef.
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=
Add_from_folder=Thêm_từ_thư_mục
diff --git a/src/main/resources/l10n/JabRef_zh.properties b/src/main/resources/l10n/JabRef_zh.properties
index cac4a529d81..4a01101ba3d 100644
--- a/src/main/resources/l10n/JabRef_zh.properties
+++ b/src/main/resources/l10n/JabRef_zh.properties
@@ -51,6 +51,8 @@ The_path_need_not_be_on_the_classpath_of_JabRef.=该路径不需要在_JabRef_
Add_a_(compiled)_custom_Importer_class_from_a_ZIP-archive.=从一个_ZIP_压缩包中添加(编译好的)自定义导入类。
The_ZIP-archive_need_not_be_on_the_classpath_of_JabRef.=该_ZIP_压缩包不需要在_JabRef_的_classpath_下。
+Add_a_regular_expression_for_the_key_pattern.=
+
Add_selected_entries_to_this_group=添加选定记录到该组
Add_from_folder=从文件夹中添加
diff --git a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtilTest.java b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtilTest.java
index f9e5fd5e03b..16f33e21965 100644
--- a/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtilTest.java
+++ b/src/test/java/org/jabref/logic/bibtexkeypattern/BibtexKeyPatternUtilTest.java
@@ -674,20 +674,20 @@ public void veryShortTitle() {
public void shortTitle() {
// shortTitle is getTitleWords with "3" as count
int count = 3;
- assertEquals("applicationmigrationeffort",
+ assertEquals("application migration effort",
BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_ALL_LOWER_FOUR_SMALL_WORDS_ONE_EN_DASH));
- assertEquals("BPELconformancein", BibtexKeyPatternUtil.getTitleWords(count,
+ assertEquals("BPEL conformance in", BibtexKeyPatternUtil.getTitleWords(count,
TITLE_STRING_ALL_LOWER_FIRST_WORD_IN_BRACKETS_TWO_SMALL_WORDS_SMALL_WORD_AFTER_COLON));
- assertEquals("ProcessViewingPatterns", BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED));
- assertEquals("BPMNConformancein",
+ assertEquals("Process Viewing Patterns", BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED));
+ assertEquals("BPMN Conformance in",
BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED_ONE_UPPER_WORD_ONE_SMALL_WORD));
- assertEquals("TheDifferenceBetween", BibtexKeyPatternUtil.getTitleWords(count,
+ assertEquals("The Difference Between", BibtexKeyPatternUtil.getTitleWords(count,
TITLE_STRING_CASED_TWO_SMALL_WORDS_SMALL_WORD_AT_THE_BEGINNING));
- assertEquals("CloudComputingThe",
+ assertEquals("Cloud Computing: The",
BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED_TWO_SMALL_WORDS_SMALL_WORD_AFTER_COLON));
- assertEquals("TowardsChoreographybased",
+ assertEquals("Towards Choreography based",
BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED_TWO_SMALL_WORDS_ONE_CONNECTED_WORD));
- assertEquals("OntheMeasurement",
+ assertEquals("On the Measurement",
BibtexKeyPatternUtil.getTitleWords(count, TITLE_STRING_CASED_FOUR_SMALL_WORDS_TWO_CONNECTED_WORDS));
}
@@ -808,7 +808,7 @@ public void testApplyModifiers() {
BibEntry entry = new BibEntry();
entry.setField("title", "Green Scheduling of Whatever");
assertEquals("GSo", BibtexKeyPatternUtil.makeLabel(entry, "shorttitleINI", ',', new BibDatabase()));
- assertEquals("GreenSchedulingof", BibtexKeyPatternUtil.makeLabel(entry, "shorttitle",
+ assertEquals("Green Scheduling of", BibtexKeyPatternUtil.makeLabel(entry, "shorttitle",
',', new BibDatabase()));
}
diff --git a/src/test/java/org/jabref/logic/bibtexkeypattern/MakeLabelWithDatabaseTest.java b/src/test/java/org/jabref/logic/bibtexkeypattern/MakeLabelWithDatabaseTest.java
index 809b4d16ee8..8098382567f 100644
--- a/src/test/java/org/jabref/logic/bibtexkeypattern/MakeLabelWithDatabaseTest.java
+++ b/src/test/java/org/jabref/logic/bibtexkeypattern/MakeLabelWithDatabaseTest.java
@@ -123,19 +123,40 @@ public void generateDefaultKeyFirstTwoAlreadyExists() {
}
@Test
- public void generateDefaultKeyLowerModified() {
+ public void generateKeyAuthLowerModified() {
bibtexKeyPattern.setDefaultValue("[auth:lower][year]");
BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
assertEquals(Optional.of("doe2016"), entry.getCiteKeyOptional());
}
@Test
- public void generateDefaultKeyUpperModified() {
+ public void generateKeyAuthUpperModified() {
bibtexKeyPattern.setDefaultValue("[auth:upper][year]");
BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
assertEquals(Optional.of("DOE2016"), entry.getCiteKeyOptional());
}
+ @Test
+ public void generateKeyAuthTitleCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[auth:title_case][year]");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Doe2016"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyAuthSentenceCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[auth:sentence_case][year]");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Doe2016"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyAuthCapitalizeModified() {
+ bibtexKeyPattern.setDefaultValue("[auth:capitalize][year]");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Doe2016"), entry.getCiteKeyOptional());
+ }
+
@Test
public void generateDefaultKeyFixedValue() {
bibtexKeyPattern.setDefaultValue("[auth]Test[year]");
@@ -208,6 +229,46 @@ public void generateKeyShorttitle() {
assertEquals(Optional.of("Anawesomepaper"), entry.getCiteKeyOptional());
}
+ @Test
+ public void generateKeyShorttitleLowerModified() {
+ bibtexKeyPattern.setDefaultValue("[shorttitle:lower]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("anawesomepaper"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyShorttitleUpperModified() {
+ bibtexKeyPattern.setDefaultValue("[shorttitle:upper]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("ANAWESOMEPAPER"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyShorttitleTitleCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[shorttitle:title_case]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("AnAwesomePaper"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyShorttitleSentenceCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[shorttitle:sentence_case]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Anawesomepaper"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyShorttitleCapitalizeModified() {
+ bibtexKeyPattern.setDefaultValue("[shorttitle:capitalize]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("AnAwesomePaper"), entry.getCiteKeyOptional());
+ }
+
@Test
public void generateKeyVeryshorttitle() {
bibtexKeyPattern.setDefaultValue("[veryshorttitle]");
@@ -215,6 +276,46 @@ public void generateKeyVeryshorttitle() {
assertEquals(Optional.of("awesome"), entry.getCiteKeyOptional());
}
+ @Test
+ public void generateKeyVeryshorttitleLowerModified() {
+ bibtexKeyPattern.setDefaultValue("[veryshorttitle:lower]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("awesome"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyVeryshorttitleUpperModified() {
+ bibtexKeyPattern.setDefaultValue("[veryshorttitle:upper]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("AWESOME"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyVeryshorttitleTitleCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[veryshorttitle:title_case]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Awesome"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyVeryshorttitleSentenceCaseModified() {
+ bibtexKeyPattern.setDefaultValue("[veryshorttitle:sentence_case]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Awesome"), entry.getCiteKeyOptional());
+ }
+
+ @Test
+ public void generateKeyVeryshorttitleCapitalizeModified() {
+ bibtexKeyPattern.setDefaultValue("[veryshorttitle:capitalize]");
+ entry.setField("title", "An aweSOme Paper on JabRef");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Awesome"), entry.getCiteKeyOptional());
+ }
+
@Test
public void generateKeyShorttitleINI() {
bibtexKeyPattern.setDefaultValue("[shorttitleINI]");
@@ -286,6 +387,14 @@ public void generateKeyAuthIniMany() {
assertEquals(Optional.of("DoeSmiWon"), entry.getCiteKeyOptional());
}
+ @Test
+ public void generateKeyTitleRegexe() {
+ bibtexKeyPattern.setDefaultValue("[title:regex(\" \",\"-\")]");
+ entry.setField("title", "Please replace the spaces");
+ BibtexKeyPatternUtil.makeAndSetLabel(bibtexKeyPattern, database, entry, preferences);
+ assertEquals(Optional.of("Please-Replace-the-Spaces"), entry.getCiteKeyOptional());
+ }
+
@Test
public void generateKeyTitleTitleCase() {
bibtexKeyPattern.setDefaultValue("[title:title_case]");
diff --git a/src/test/java/org/jabref/logic/formatter/FormatterTest.java b/src/test/java/org/jabref/logic/formatter/FormatterTest.java
index ecb7a695b06..1fdc8231a35 100644
--- a/src/test/java/org/jabref/logic/formatter/FormatterTest.java
+++ b/src/test/java/org/jabref/logic/formatter/FormatterTest.java
@@ -13,6 +13,7 @@
import org.jabref.logic.formatter.bibtexfields.NormalizeNamesFormatter;
import org.jabref.logic.formatter.bibtexfields.NormalizePagesFormatter;
import org.jabref.logic.formatter.bibtexfields.OrdinalsToSuperscriptFormatter;
+import org.jabref.logic.formatter.bibtexfields.RegexFormatter;
import org.jabref.logic.formatter.bibtexfields.RemoveBracesFormatter;
import org.jabref.logic.formatter.bibtexfields.UnicodeToLatexFormatter;
import org.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter;
@@ -123,6 +124,7 @@ public static Collection