|
4 | 4 |
|
5 | 5 |
|
6 | 6 | import logging |
| 7 | +from enum import Enum, auto |
| 8 | +from typing import Dict, Callable, Iterable |
7 | 9 | from bibtexparser.bibdatabase import (BibDatabase, COMMON_STRINGS, |
8 | 10 | BibDataString, |
9 | 11 | BibDataStringExpression) |
|
14 | 16 | __all__ = ['BibTexWriter'] |
15 | 17 |
|
16 | 18 |
|
| 19 | +class SortingStrategy(Enum): |
| 20 | + """ |
| 21 | + Defines different strategies for sorting the entries not defined in :py:attr:`~.BibTexWriter.display_order` and that are added at the end. |
| 22 | + """ |
| 23 | + ALPHABETICAL_ASC = auto() |
| 24 | + """ |
| 25 | + Alphabetical sorting in ascending order. |
| 26 | + """ |
| 27 | + ALPHABETICAL_DESC = auto() |
| 28 | + """ |
| 29 | + Alphabetical sorting in descending order. |
| 30 | + """ |
| 31 | + PRESERVE = auto() |
| 32 | + """ |
| 33 | + Preserves the order of the entries. Entries are not sorted. |
| 34 | + """ |
| 35 | + |
| 36 | + |
| 37 | +def _apply_sorting_strategy(strategy: SortingStrategy, items: Iterable[str]) -> Iterable[str]: |
| 38 | + """ |
| 39 | + Sorts the items based on the given sorting strategy. |
| 40 | + """ |
| 41 | + if strategy == SortingStrategy.ALPHABETICAL_ASC: |
| 42 | + return sorted(items) |
| 43 | + elif strategy == SortingStrategy.ALPHABETICAL_DESC: |
| 44 | + return reversed(sorted(items)) |
| 45 | + elif strategy == SortingStrategy.PRESERVE: |
| 46 | + return items |
| 47 | + else: |
| 48 | + raise NotImplementedError(f"The strategy {strategy.name} is not implemented.") |
| 49 | + |
| 50 | + |
17 | 51 | def to_bibtex(parsed): |
18 | 52 | """ |
19 | 53 | Convenience function for backwards compatibility. |
@@ -65,9 +99,12 @@ def __init__(self, write_common_strings=False): |
65 | 99 | self.entry_separator = '\n' |
66 | 100 | #: Tuple of fields for ordering BibTeX entries. Set to `None` to disable sorting. Default: BibTeX key `('ID', )`. |
67 | 101 | self.order_entries_by = ('ID', ) |
68 | | - #: Tuple of fields for display order in a single BibTeX entry. Fields not listed here will be displayed |
69 | | - #: alphabetically at the end. Set to '[]' for alphabetical order. Default: '[]' |
| 102 | + #: Tuple of fields for display order in a single BibTeX entry. Fields not listed here will be displayed at the |
| 103 | + # end in the order defined by display_order_sorting. Default: '[]' |
70 | 104 | self.display_order = [] |
| 105 | + # Sorting strategy for entries not contained in display_order. Entries not defined in display_order are added |
| 106 | + # at the end in the order defined by this strategy. Default: SortingStrategy.ALPHABETICAL_ASC |
| 107 | + self.display_order_sorting: SortingStrategy = SortingStrategy.ALPHABETICAL_ASC |
71 | 108 | #: BibTeX syntax allows comma first syntax |
72 | 109 | #: (common in functional languages), use this to enable |
73 | 110 | #: comma first syntax as the bwriter output |
@@ -122,7 +159,7 @@ def _entry_to_bibtex(self, entry): |
122 | 159 | # first those keys which are both in self.display_order and in entry.keys |
123 | 160 | display_order = [i for i in self.display_order if i in entry] |
124 | 161 | # then all the other fields sorted alphabetically |
125 | | - display_order += [i for i in sorted(entry) if i not in self.display_order] |
| 162 | + display_order += [i for i in _apply_sorting_strategy(self.display_order_sorting, entry) if i not in self.display_order] |
126 | 163 | if self.comma_first: |
127 | 164 | field_fmt = u"\n{indent}, {field:<{field_max_w}} = {value}" |
128 | 165 | else: |
|
0 commit comments