omdev 0.0.0.dev440__py3-none-any.whl → 0.0.0.dev486__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- omdev/.omlish-manifests.json +17 -29
- omdev/__about__.py +9 -7
- omdev/amalg/gen/gen.py +49 -6
- omdev/amalg/gen/imports.py +1 -1
- omdev/amalg/gen/manifests.py +1 -1
- omdev/amalg/gen/resources.py +1 -1
- omdev/amalg/gen/srcfiles.py +13 -3
- omdev/amalg/gen/strip.py +1 -1
- omdev/amalg/gen/types.py +1 -1
- omdev/amalg/gen/typing.py +1 -1
- omdev/amalg/info.py +32 -0
- omdev/cache/data/actions.py +1 -1
- omdev/cache/data/specs.py +1 -1
- omdev/cexts/_boilerplate.cc +2 -3
- omdev/cexts/cmake.py +4 -1
- omdev/ci/cli.py +1 -2
- omdev/cmdlog/cli.py +1 -2
- omdev/dataclasses/_dumping.py +1960 -0
- omdev/dataclasses/_template.py +22 -0
- omdev/dataclasses/cli.py +6 -1
- omdev/dataclasses/codegen.py +340 -60
- omdev/dataclasses/dumping.py +200 -0
- omdev/interp/uv/provider.py +1 -0
- omdev/interp/venvs.py +1 -0
- omdev/irc/messages/base.py +50 -0
- omdev/irc/messages/formats.py +92 -0
- omdev/irc/messages/messages.py +775 -0
- omdev/irc/messages/parsing.py +99 -0
- omdev/irc/numerics/__init__.py +0 -0
- omdev/irc/numerics/formats.py +97 -0
- omdev/irc/numerics/numerics.py +865 -0
- omdev/irc/numerics/types.py +59 -0
- omdev/irc/protocol/LICENSE +11 -0
- omdev/irc/protocol/__init__.py +61 -0
- omdev/irc/protocol/consts.py +6 -0
- omdev/irc/protocol/errors.py +30 -0
- omdev/irc/protocol/message.py +21 -0
- omdev/irc/protocol/nuh.py +55 -0
- omdev/irc/protocol/parsing.py +158 -0
- omdev/irc/protocol/rendering.py +153 -0
- omdev/irc/protocol/tags.py +102 -0
- omdev/irc/protocol/utils.py +30 -0
- omdev/manifests/_dumping.py +125 -25
- omdev/markdown/__init__.py +0 -0
- omdev/markdown/incparse.py +116 -0
- omdev/markdown/tokens.py +51 -0
- omdev/packaging/marshal.py +8 -8
- omdev/packaging/requires.py +6 -6
- omdev/packaging/specifiers.py +2 -1
- omdev/packaging/versions.py +4 -4
- omdev/packaging/wheelfile.py +2 -0
- omdev/precheck/blanklines.py +66 -0
- omdev/precheck/caches.py +1 -1
- omdev/precheck/imports.py +14 -1
- omdev/precheck/main.py +4 -3
- omdev/precheck/unicode.py +39 -15
- omdev/py/asts/__init__.py +0 -0
- omdev/py/asts/parents.py +28 -0
- omdev/py/asts/toplevel.py +123 -0
- omdev/py/asts/visitors.py +18 -0
- omdev/py/attrdocs.py +1 -1
- omdev/py/bracepy.py +12 -4
- omdev/py/reprs.py +32 -0
- omdev/py/srcheaders.py +1 -1
- omdev/py/tokens/__init__.py +0 -0
- omdev/py/tools/mkrelimp.py +1 -1
- omdev/py/tools/pipdepup.py +629 -0
- omdev/pyproject/pkg.py +190 -45
- omdev/pyproject/reqs.py +31 -9
- omdev/pyproject/tools/__init__.py +0 -0
- omdev/pyproject/tools/aboutdeps.py +55 -0
- omdev/pyproject/venvs.py +8 -1
- omdev/rs/__init__.py +0 -0
- omdev/scripts/ci.py +398 -80
- omdev/scripts/interp.py +193 -35
- omdev/scripts/lib/inject.py +74 -27
- omdev/scripts/lib/logs.py +75 -27
- omdev/scripts/lib/marshal.py +67 -25
- omdev/scripts/pyproject.py +941 -90
- omdev/tools/git/cli.py +10 -0
- omdev/tools/json/processing.py +5 -2
- omdev/tools/jsonview/cli.py +31 -5
- omdev/tools/pawk/pawk.py +2 -2
- omdev/tools/pip.py +8 -0
- omdev/tui/__init__.py +0 -0
- omdev/tui/apps/__init__.py +0 -0
- omdev/tui/apps/edit/__init__.py +0 -0
- omdev/tui/apps/edit/main.py +163 -0
- omdev/tui/apps/irc/__init__.py +0 -0
- omdev/tui/apps/irc/__main__.py +4 -0
- omdev/tui/apps/irc/app.py +278 -0
- omdev/tui/apps/irc/client.py +187 -0
- omdev/tui/apps/irc/commands.py +175 -0
- omdev/tui/apps/irc/main.py +26 -0
- omdev/tui/apps/markdown/__init__.py +0 -0
- omdev/tui/apps/markdown/__main__.py +11 -0
- omdev/{ptk → tui/apps}/markdown/cli.py +5 -7
- omdev/tui/rich/__init__.py +34 -0
- omdev/tui/rich/console2.py +20 -0
- omdev/tui/rich/markdown2.py +186 -0
- omdev/tui/textual/__init__.py +226 -0
- omdev/tui/textual/app2.py +11 -0
- omdev/tui/textual/autocomplete/LICENSE +21 -0
- omdev/tui/textual/autocomplete/__init__.py +33 -0
- omdev/tui/textual/autocomplete/matching.py +226 -0
- omdev/tui/textual/autocomplete/paths.py +202 -0
- omdev/tui/textual/autocomplete/widget.py +612 -0
- omdev/tui/textual/drivers2.py +55 -0
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/METADATA +11 -9
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/RECORD +119 -73
- omdev/ptk/__init__.py +0 -103
- omdev/ptk/apps/ncdu.py +0 -167
- omdev/ptk/confirm.py +0 -60
- omdev/ptk/markdown/LICENSE +0 -22
- omdev/ptk/markdown/__init__.py +0 -10
- omdev/ptk/markdown/__main__.py +0 -11
- omdev/ptk/markdown/border.py +0 -94
- omdev/ptk/markdown/markdown.py +0 -390
- omdev/ptk/markdown/parser.py +0 -42
- omdev/ptk/markdown/styles.py +0 -29
- omdev/ptk/markdown/tags.py +0 -299
- omdev/ptk/markdown/utils.py +0 -366
- omdev/pyproject/cexts.py +0 -110
- /omdev/{ptk/apps → irc}/__init__.py +0 -0
- /omdev/{tokens → irc/messages}/__init__.py +0 -0
- /omdev/{tokens → py/tokens}/all.py +0 -0
- /omdev/{tokens → py/tokens}/tokenizert.py +0 -0
- /omdev/{tokens → py/tokens}/utils.py +0 -0
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/licenses/LICENSE +0 -0
- {omdev-0.0.0.dev440.dist-info → omdev-0.0.0.dev486.dist-info}/top_level.txt +0 -0
omdev/ptk/apps/ncdu.py
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
TODO:
|
|
3
|
-
- reuse dir sizes lol
|
|
4
|
-
"""
|
|
5
|
-
import dataclasses as dc
|
|
6
|
-
import os
|
|
7
|
-
import typing as ta
|
|
8
|
-
|
|
9
|
-
from omlish.lite.strings import format_num_bytes
|
|
10
|
-
|
|
11
|
-
from ... import ptk
|
|
12
|
-
from ...cli import CliModule
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def get_directory_size(path: str) -> int:
|
|
19
|
-
total_size = 0
|
|
20
|
-
for dirpath, _, filenames in os.walk(path):
|
|
21
|
-
for f in filenames:
|
|
22
|
-
fp = os.path.join(dirpath, f)
|
|
23
|
-
try:
|
|
24
|
-
total_size += os.path.getsize(fp) # noqa
|
|
25
|
-
except OSError:
|
|
26
|
-
pass
|
|
27
|
-
return total_size
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@dc.dataclass(frozen=True)
|
|
31
|
-
class Entry:
|
|
32
|
-
name: str
|
|
33
|
-
size: int
|
|
34
|
-
type: ta.Literal['dir', 'file']
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def scan_directory(path: str) -> list[Entry]:
|
|
38
|
-
entries: list[Entry] = []
|
|
39
|
-
|
|
40
|
-
with os.scandir(path) as it:
|
|
41
|
-
for entry in it:
|
|
42
|
-
if entry.is_dir(follow_symlinks=False):
|
|
43
|
-
size = get_directory_size(entry.path)
|
|
44
|
-
entries.append(Entry(entry.name + '/', size, 'dir'))
|
|
45
|
-
|
|
46
|
-
elif entry.is_file(follow_symlinks=False):
|
|
47
|
-
size = entry.stat().st_size
|
|
48
|
-
entries.append(Entry(entry.name, size, 'file'))
|
|
49
|
-
|
|
50
|
-
entries.sort(key=lambda x: x.size, reverse=True)
|
|
51
|
-
return entries
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class NcduApp:
|
|
55
|
-
def __init__(self, root_path: str) -> None:
|
|
56
|
-
super().__init__()
|
|
57
|
-
|
|
58
|
-
self._root_path = root_path
|
|
59
|
-
self._current_path = root_path
|
|
60
|
-
|
|
61
|
-
self._entries_by_path: dict[str, list[Entry]] = {}
|
|
62
|
-
self._entries = self._get_entries(root_path)
|
|
63
|
-
|
|
64
|
-
self._cursor = 0
|
|
65
|
-
|
|
66
|
-
self._text_area = ptk.TextArea(
|
|
67
|
-
read_only=True,
|
|
68
|
-
)
|
|
69
|
-
self._text_area.window.always_hide_cursor = ptk.to_filter(True)
|
|
70
|
-
|
|
71
|
-
self.update_display()
|
|
72
|
-
|
|
73
|
-
self._kb = ptk.KeyBindings()
|
|
74
|
-
self._kb.add('q')(self.exit_app)
|
|
75
|
-
for k in ['up', 'p']:
|
|
76
|
-
self._kb.add(k)(self.move_up)
|
|
77
|
-
for k in ['down', 'n']:
|
|
78
|
-
self._kb.add(k)(self.move_down)
|
|
79
|
-
for k in ['right', 'enter']:
|
|
80
|
-
self._kb.add(k)(self.enter_directory)
|
|
81
|
-
for k in ['left', 'backspace']:
|
|
82
|
-
self._kb.add(k)(self.go_back)
|
|
83
|
-
|
|
84
|
-
self._layout = ptk.Layout(ptk.Frame(self._text_area))
|
|
85
|
-
|
|
86
|
-
self._style = ptk.Style.from_dict({
|
|
87
|
-
'frame': 'bg:#008800 bold',
|
|
88
|
-
'text-area': 'bg:#000000 fg:#ffffff',
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
self._app: ptk.Application = ptk.Application(
|
|
92
|
-
layout=self._layout,
|
|
93
|
-
key_bindings=self._kb,
|
|
94
|
-
style=self._style,
|
|
95
|
-
full_screen=True,
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
def _get_entries(self, path: str) -> list[Entry]:
|
|
99
|
-
try:
|
|
100
|
-
return self._entries_by_path[path]
|
|
101
|
-
except KeyError:
|
|
102
|
-
pass
|
|
103
|
-
entries = self._entries_by_path[path] = scan_directory(path)
|
|
104
|
-
return entries
|
|
105
|
-
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
def update_display(self) -> None:
|
|
109
|
-
display_text = f'Current Directory: {self._current_path}\n\n'
|
|
110
|
-
for i, e in enumerate(self._entries):
|
|
111
|
-
indicator = '>' if i == self._cursor else ' '
|
|
112
|
-
display_text += f'{indicator} {e.name:<40} {format_num_bytes(e.size):>10}\n'
|
|
113
|
-
self._text_area.text = display_text
|
|
114
|
-
|
|
115
|
-
#
|
|
116
|
-
|
|
117
|
-
def move_up(self, event: ptk.KeyPressEvent) -> None:
|
|
118
|
-
if self._cursor > 0:
|
|
119
|
-
self._cursor -= 1
|
|
120
|
-
self.update_display()
|
|
121
|
-
|
|
122
|
-
def move_down(self, event: ptk.KeyPressEvent) -> None:
|
|
123
|
-
if self._cursor < len(self._entries) - 1:
|
|
124
|
-
self._cursor += 1
|
|
125
|
-
self.update_display()
|
|
126
|
-
|
|
127
|
-
def enter_directory(self, event: ptk.KeyPressEvent) -> None:
|
|
128
|
-
selected_entry = self._entries[self._cursor]
|
|
129
|
-
if selected_entry.type == 'dir':
|
|
130
|
-
self._current_path = os.path.join(self._current_path, selected_entry.name[:-1])
|
|
131
|
-
self._entries = self._get_entries(self._current_path)
|
|
132
|
-
self._cursor = 0
|
|
133
|
-
self.update_display()
|
|
134
|
-
|
|
135
|
-
def go_back(self, event: ptk.KeyPressEvent) -> None:
|
|
136
|
-
if self._current_path != self._root_path:
|
|
137
|
-
self._current_path = os.path.dirname(self._current_path)
|
|
138
|
-
self._entries = self._get_entries(self._current_path)
|
|
139
|
-
self._cursor = 0
|
|
140
|
-
self.update_display()
|
|
141
|
-
|
|
142
|
-
def exit_app(self, event: ptk.KeyPressEvent) -> None:
|
|
143
|
-
event.app.exit()
|
|
144
|
-
|
|
145
|
-
#
|
|
146
|
-
|
|
147
|
-
def run(self) -> None:
|
|
148
|
-
self._app.run()
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def _main() -> None:
|
|
152
|
-
import argparse
|
|
153
|
-
|
|
154
|
-
parser = argparse.ArgumentParser()
|
|
155
|
-
parser.add_argument('dir', default='.', nargs='?')
|
|
156
|
-
args = parser.parse_args()
|
|
157
|
-
|
|
158
|
-
ncdu_app = NcduApp(args.dir)
|
|
159
|
-
ncdu_app.run()
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
# @omlish-manifest
|
|
163
|
-
_CLI_MODULE = CliModule('ptk/ncdu', __name__)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if __name__ == '__main__':
|
|
167
|
-
_main()
|
omdev/ptk/confirm.py
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import typing as ta
|
|
2
|
-
|
|
3
|
-
from prompt_toolkit.formatted_text import merge_formatted_text
|
|
4
|
-
from prompt_toolkit.key_binding import KeyBindings
|
|
5
|
-
from prompt_toolkit.key_binding import KeyPressEvent
|
|
6
|
-
from prompt_toolkit.shortcuts import PromptSession
|
|
7
|
-
|
|
8
|
-
from omlish import check
|
|
9
|
-
from omlish import lang
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def create_strict_confirm_session(
|
|
16
|
-
message: str,
|
|
17
|
-
suffix: str = ' (y/n) ',
|
|
18
|
-
) -> PromptSession[str | bool]:
|
|
19
|
-
"""Create a `PromptSession` object for the 'confirm' function."""
|
|
20
|
-
|
|
21
|
-
bindings = KeyBindings()
|
|
22
|
-
|
|
23
|
-
@bindings.add('y')
|
|
24
|
-
@bindings.add('Y')
|
|
25
|
-
def yes(event: KeyPressEvent) -> None:
|
|
26
|
-
session.default_buffer.text = 'y'
|
|
27
|
-
event.app.exit(result=True)
|
|
28
|
-
|
|
29
|
-
@bindings.add('n')
|
|
30
|
-
@bindings.add('N')
|
|
31
|
-
def no(event: KeyPressEvent) -> None:
|
|
32
|
-
session.default_buffer.text = 'n'
|
|
33
|
-
event.app.exit(result=False)
|
|
34
|
-
|
|
35
|
-
complete_message = merge_formatted_text([message, suffix])
|
|
36
|
-
session: PromptSession[str | bool] = PromptSession(
|
|
37
|
-
complete_message,
|
|
38
|
-
key_bindings=bindings,
|
|
39
|
-
)
|
|
40
|
-
return session
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
async def strict_confirm(message: str = 'Confirm?', suffix: str = ' (y/n) ') -> bool:
|
|
47
|
-
"""Display a confirmation prompt that returns True/False. Requires an explicit answer."""
|
|
48
|
-
|
|
49
|
-
while True:
|
|
50
|
-
session = create_strict_confirm_session(message, suffix)
|
|
51
|
-
ret = await lang.make_maysync(session.prompt, ta.cast(ta.Any, session.prompt_async))()
|
|
52
|
-
|
|
53
|
-
if isinstance(ret, str):
|
|
54
|
-
check.empty(ret)
|
|
55
|
-
|
|
56
|
-
elif isinstance(ret, bool):
|
|
57
|
-
return ret
|
|
58
|
-
|
|
59
|
-
else:
|
|
60
|
-
raise TypeError(ret)
|
omdev/ptk/markdown/LICENSE
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2014, Jonathan Slenders
|
|
2
|
-
All rights reserved.
|
|
3
|
-
|
|
4
|
-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
|
5
|
-
following conditions are met:
|
|
6
|
-
|
|
7
|
-
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
|
8
|
-
disclaimer.
|
|
9
|
-
|
|
10
|
-
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
11
|
-
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
12
|
-
|
|
13
|
-
* Neither the name of the {organization} nor the names of its contributors may be used to endorse or promote products
|
|
14
|
-
derived from this software without specific prior written permission.
|
|
15
|
-
|
|
16
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
17
|
-
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
19
|
-
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
20
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
21
|
-
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
22
|
-
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
omdev/ptk/markdown/__init__.py
DELETED
omdev/ptk/markdown/__main__.py
DELETED
omdev/ptk/markdown/border.py
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
##
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Border(metaclass=abc.ABCMeta):
|
|
8
|
-
"""Base border type."""
|
|
9
|
-
|
|
10
|
-
TOP_LEFT: str
|
|
11
|
-
TOP_SPLIT: str
|
|
12
|
-
TOP_RIGHT: str
|
|
13
|
-
HORIZONTAL: str
|
|
14
|
-
VERTICAL: str
|
|
15
|
-
LEFT_SPLIT: str
|
|
16
|
-
RIGHT_SPLIT: str
|
|
17
|
-
CROSS: str
|
|
18
|
-
BOTTOM_LEFT: str
|
|
19
|
-
BOTTOM_SPLIT: str
|
|
20
|
-
BOTTOM_RIGHT: str
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class NoBorder(Border):
|
|
24
|
-
"""Invisible border."""
|
|
25
|
-
|
|
26
|
-
TOP_LEFT = ' '
|
|
27
|
-
TOP_SPLIT = ' '
|
|
28
|
-
TOP_RIGHT = ' '
|
|
29
|
-
HORIZONTAL = ' '
|
|
30
|
-
INNER_VERTICAL = ' '
|
|
31
|
-
VERTICAL = ' '
|
|
32
|
-
LEFT_SPLIT = ' '
|
|
33
|
-
RIGHT_SPLIT = ' '
|
|
34
|
-
CROSS = ' '
|
|
35
|
-
BOTTOM_LEFT = ' '
|
|
36
|
-
BOTTOM_SPLIT = ' '
|
|
37
|
-
BOTTOM_RIGHT = ' '
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class SquareBorder(Border):
|
|
41
|
-
"""Square thin border."""
|
|
42
|
-
|
|
43
|
-
TOP_LEFT = '┌'
|
|
44
|
-
TOP_SPLIT = '┬'
|
|
45
|
-
TOP_RIGHT = '┐'
|
|
46
|
-
HORIZONTAL = '─'
|
|
47
|
-
VERTICAL = '│'
|
|
48
|
-
LEFT_SPLIT = '├'
|
|
49
|
-
RIGHT_SPLIT = '┤'
|
|
50
|
-
CROSS = '┼'
|
|
51
|
-
BOTTOM_LEFT = '└'
|
|
52
|
-
BOTTOM_SPLIT = '┴'
|
|
53
|
-
BOTTOM_RIGHT = '┘'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class RoundBorder(SquareBorder):
|
|
57
|
-
"""Thin border with round corners."""
|
|
58
|
-
|
|
59
|
-
TOP_LEFT = '╭'
|
|
60
|
-
TOP_RIGHT = '╮'
|
|
61
|
-
BOTTOM_LEFT = '╰'
|
|
62
|
-
BOTTOM_RIGHT = '╯'
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class DoubleBorder(Border):
|
|
66
|
-
"""Square border with double lines."""
|
|
67
|
-
|
|
68
|
-
TOP_LEFT = '╔'
|
|
69
|
-
TOP_SPLIT = '╦'
|
|
70
|
-
TOP_RIGHT = '╗'
|
|
71
|
-
HORIZONTAL = '═'
|
|
72
|
-
VERTICAL = '║'
|
|
73
|
-
LEFT_SPLIT = '╠'
|
|
74
|
-
RIGHT_SPLIT = '╣'
|
|
75
|
-
CROSS = '╬'
|
|
76
|
-
BOTTOM_LEFT = '╚'
|
|
77
|
-
BOTTOM_SPLIT = '╩'
|
|
78
|
-
BOTTOM_RIGHT = '╝'
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class ThickBorder(Border):
|
|
82
|
-
"""Square border with thick lines."""
|
|
83
|
-
|
|
84
|
-
TOP_LEFT = '┏'
|
|
85
|
-
TOP_SPLIT = '┳'
|
|
86
|
-
TOP_RIGHT = '┓'
|
|
87
|
-
HORIZONTAL = '━'
|
|
88
|
-
VERTICAL = '┃'
|
|
89
|
-
LEFT_SPLIT = '┣'
|
|
90
|
-
RIGHT_SPLIT = '┫'
|
|
91
|
-
CROSS = '╋'
|
|
92
|
-
BOTTOM_LEFT = '┗'
|
|
93
|
-
BOTTOM_SPLIT = '┻'
|
|
94
|
-
BOTTOM_RIGHT = '┛'
|