1#!/usr/bin/env python3
2"""
3
4See EOF for license/metadata/notes as applicable
5"""
6
7# Imports:
8from __future__ import annotations
9
10# ##-- stdlib imports
11import datetime
12import enum
13import functools as ftz
14import itertools as itz
15import logging as logmod
16import pathlib as pl
17import re
18import time
19import types
20import weakref
21from uuid import UUID, uuid1
22
23# ##-- end stdlib imports
24
25# ##-- 3rd party imports
26from jgdv import Proto
27import bibtexparser
28import bibtexparser.model as model
29from bibtexparser import middlewares as ms
30from bibtexparser.middlewares.middleware import (BlockMiddleware,
31 LibraryMiddleware)
32
33# ##-- end 3rd party imports
34
35from bibble._interface import ReadTime_p
36from bibble.util.middlecore import IdenBlockMiddleware
37from . import _interface as API_F
38
39# ##-- types
40# isort: off
41import abc
42import collections.abc
43from typing import TYPE_CHECKING, cast, assert_type, assert_never
44from typing import Generic, NewType, Never
45# Protocols:
46from typing import Protocol, runtime_checkable
47# Typing Decorators:
48from typing import no_type_check, final, override, overload
49
50if TYPE_CHECKING:
51 from jgdv import Maybe
52 from typing import Final
53 from typing import ClassVar, Any, LiteralString
54 from typing import Self, Literal
55 from typing import TypeGuard
56 from collections.abc import Iterable, Iterator, Callable, Generator
57 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
58
59 type Entry = model.Entry
60 from bibtexparser.library import Library
61
62##--|
63
64# isort: on
65# ##-- end types
66
67##-- logging
68logging = logmod.getLogger(__name__)
69##-- end logging
70
71##--|
72
[docs]
73@Proto(ReadTime_p)
74class TitleCleaner(IdenBlockMiddleware):
75 """
76 strip whitespace from the title, and (optional) subtitle
77 """
78
[docs]
79 def on_read(self):
80 Never()
81
[docs]
82 def transform_Entry(self, entry, library):
83 match entry.get(API_F.TITLE_K):
84 case None:
85 self._logger.warning("Entry has no title: %s", entry.key)
86 case model.Field(value=str() as value):
87 entry.set_field(model.Field(API_F.TITLE_K, value.strip()))
88 case _:
89 pass
90
91 match entry.get(API_F.SUBTITLE_K):
92 case None:
93 pass
94 case model.Field(value=str() as value):
95 entry.set_field(model.Field(API_F.SUBTITLE_K, value.strip()))
96 case _:
97 pass
98
99 return [entry]
100
[docs]
101@Proto(ReadTime_p)
102class TitleSplitter(IdenBlockMiddleware):
103 """
104 Split Title Into Title and Subtitle, If Subtitle Doesn't Exist Yet
105
106 strips whitespace as well
107 """
108
[docs]
109 def on_read(self):
110 Never()
111
[docs]
112 def transform_Entry(self, entry:Entry, library:Library):
113 match entry.get(API_F.TITLE_K), entry.get(API_F.SUBTITLE_K):
114 case None, _:
115 self._logger.warning("Entry has no title: %s", entry.key)
116 case model.Field(value=title), model.Field(value=subtitle):
117 entry.set_field(model.Field(API_F.TITLE_K, title.strip()))
118 entry.set_field(model.Field(API_F.SUBTITLE_K, subtitle.strip()))
119 pass
120 case model.Field(value=value), None if API_F.TITLE_SEP in value:
121 title, *rest = value.split(API_F.TITLE_SEP)
122 entry.set_field(model.Field(API_F.TITLE_K, title.strip()))
123 entry.set_field(model.Field(API_F.SUBTITLE_K, " ".join(rest).strip()))
124 case model.Field(value=value), None:
125 entry.set_field(model.Field(API_F.TITLE_K, value.strip()))
126 case None, None:
127 pass
128
129 return [entry]