nbcat 0.12.1__py3-none-any.whl → 0.13.0__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.
- nbcat/__init__.py +1 -1
- nbcat/main.py +36 -11
- nbcat/pager.py +82 -0
- {nbcat-0.12.1.dist-info → nbcat-0.13.0.dist-info}/METADATA +6 -4
- nbcat-0.13.0.dist-info/RECORD +14 -0
- nbcat-0.12.1.dist-info/RECORD +0 -13
- {nbcat-0.12.1.dist-info → nbcat-0.13.0.dist-info}/WHEEL +0 -0
- {nbcat-0.12.1.dist-info → nbcat-0.13.0.dist-info}/entry_points.txt +0 -0
- {nbcat-0.12.1.dist-info → nbcat-0.13.0.dist-info}/licenses/LICENSE +0 -0
nbcat/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.13.0"
|
nbcat/main.py
CHANGED
@@ -22,6 +22,7 @@ from .exceptions import (
|
|
22
22
|
)
|
23
23
|
from .image import Image
|
24
24
|
from .markdown import Markdown
|
25
|
+
from .pager import Pager
|
25
26
|
from .schemas import Cell, Notebook
|
26
27
|
|
27
28
|
console = Console()
|
@@ -135,20 +136,26 @@ def render_cell(cell: Cell) -> RenderableType:
|
|
135
136
|
return Group(*rows)
|
136
137
|
|
137
138
|
|
138
|
-
def
|
139
|
+
def render_notebook(nb: Notebook) -> list[RenderableType]:
|
139
140
|
"""
|
140
|
-
|
141
|
+
Convert a Notebook object into a list of rich renderables for terminal display.
|
142
|
+
|
143
|
+
Each cell in the notebook is processed and rendered using `render_cell`,
|
144
|
+
producing a sequence of styled input/output blocks suitable for use in a
|
145
|
+
Textual or Rich-based terminal UI.
|
141
146
|
|
142
147
|
Args:
|
143
|
-
nb (Notebook):
|
144
|
-
"""
|
145
|
-
if not nb.cells:
|
146
|
-
console.print("[bold red]Notebook contains no cells.")
|
147
|
-
return
|
148
|
+
nb (Notebook): The notebook object containing parsed cells (e.g., from a .ipynb file).
|
148
149
|
|
150
|
+
Returns
|
151
|
+
-------
|
152
|
+
list[RenderableType]: A list of rich renderable objects representing the notebook cells.
|
153
|
+
Returns an empty list if the notebook has no cells.
|
154
|
+
"""
|
155
|
+
rendered: list[RenderableType] = []
|
149
156
|
for cell in nb.cells:
|
150
|
-
rendered
|
151
|
-
|
157
|
+
rendered.append(render_cell(cell))
|
158
|
+
return rendered
|
152
159
|
|
153
160
|
|
154
161
|
def main():
|
@@ -160,20 +167,38 @@ def main():
|
|
160
167
|
"file", help="Path or URL to a .ipynb notebook", type=str
|
161
168
|
).completer = FilesCompleter()
|
162
169
|
parser.add_argument(
|
170
|
+
"-v",
|
163
171
|
"--version",
|
164
172
|
help="print version information and quite",
|
165
173
|
action="version",
|
166
174
|
version=__version__,
|
167
175
|
)
|
168
176
|
parser.add_argument(
|
169
|
-
"--debug", help="enable extended error output", action="store_true", default=False
|
177
|
+
"-d", "--debug", help="enable extended error output", action="store_true", default=False
|
178
|
+
)
|
179
|
+
parser.add_argument(
|
180
|
+
"-p",
|
181
|
+
"--page",
|
182
|
+
help="enable paginated view mode (similar to less)",
|
183
|
+
action="store_true",
|
184
|
+
default=False,
|
170
185
|
)
|
171
186
|
|
172
187
|
try:
|
173
188
|
argcomplete.autocomplete(parser)
|
174
189
|
args = parser.parse_args()
|
190
|
+
|
175
191
|
notebook = read_notebook(args.file, debug=args.debug)
|
176
|
-
|
192
|
+
objects = render_notebook(notebook)
|
193
|
+
|
194
|
+
if not objects:
|
195
|
+
console.print("[bold red]Notebook contains no cells.")
|
196
|
+
return
|
197
|
+
|
198
|
+
if args.page:
|
199
|
+
Pager(objects).run()
|
200
|
+
else:
|
201
|
+
console.print(*objects)
|
177
202
|
except Exception as e:
|
178
203
|
sys.exit(f"nbcat: {e}")
|
179
204
|
|
nbcat/pager.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
from rich.console import RenderableType
|
2
|
+
from textual.app import App, ComposeResult
|
3
|
+
from textual.binding import Binding
|
4
|
+
from textual.containers import VerticalScroll
|
5
|
+
from textual.widgets import Static
|
6
|
+
|
7
|
+
|
8
|
+
class Pager(App):
|
9
|
+
BINDINGS = [
|
10
|
+
# Exit
|
11
|
+
Binding("q", "quit", "Quit"),
|
12
|
+
Binding(":q", "quit", "Quit"),
|
13
|
+
Binding("Q", "quit", "Quit"),
|
14
|
+
Binding(":Q", "quit", "Quit"),
|
15
|
+
Binding("ZZ", "quit", "Quit"),
|
16
|
+
# One line
|
17
|
+
Binding("j", "scroll_down", "Down"),
|
18
|
+
Binding("e", "scroll_down", "Down"),
|
19
|
+
Binding("^e", "scroll_down", "Down"),
|
20
|
+
Binding("^n", "scroll_down", "Down"),
|
21
|
+
Binding("cr", "scroll_down", "Down"), # carriage return = Enter
|
22
|
+
Binding("k", "scroll_up", "Up"),
|
23
|
+
Binding("y", "scroll_up", "Up"),
|
24
|
+
Binding("ctrl+y", "scroll_up", "Up"),
|
25
|
+
Binding("ctrl+k", "scroll_up", "Up"),
|
26
|
+
Binding("ctrl+p", "scroll_up", "Up"),
|
27
|
+
# One window
|
28
|
+
Binding("f", "page_down", "Page Down"),
|
29
|
+
Binding("ctrl+f", "page_down", "Page Down"),
|
30
|
+
Binding("ctrl+v", "page_down", "Page Down"),
|
31
|
+
Binding("space", "page_down", "Page Down"),
|
32
|
+
Binding("b", "page_up", "Page Up"),
|
33
|
+
Binding("ctrl+b", "page_up", "Page Up"),
|
34
|
+
Binding("escape+v", "page_up", "Page Up"),
|
35
|
+
# Extended window control
|
36
|
+
Binding("z", "page_down", "Window Down (set N)"),
|
37
|
+
Binding("w", "page_up", "Window Up (set N)"),
|
38
|
+
Binding("escape+space", "page_down", "Forward one window, no EOF stop"),
|
39
|
+
Binding("d", "half_page_down", "Half Page Down"),
|
40
|
+
Binding("ctrl+d", "half_page_down", "Half Page Down"),
|
41
|
+
# Jumping
|
42
|
+
Binding("g", "go_to_top", "Top of File"),
|
43
|
+
Binding("<", "go_to_top", "Top of File"),
|
44
|
+
Binding("escape+<", "go_to_top", "Top of File"),
|
45
|
+
Binding("G", "go_to_bottom", "Bottom of File"),
|
46
|
+
Binding(">", "go_to_bottom", "Bottom of File"),
|
47
|
+
Binding("escape+>", "go_to_bottom", "Bottom of File"),
|
48
|
+
]
|
49
|
+
|
50
|
+
def __init__(self, objects: list[RenderableType]):
|
51
|
+
super().__init__()
|
52
|
+
self._objects = objects
|
53
|
+
|
54
|
+
def compose(self) -> ComposeResult:
|
55
|
+
with VerticalScroll():
|
56
|
+
for obj in self._objects:
|
57
|
+
yield Static(obj)
|
58
|
+
|
59
|
+
def on_mount(self) -> None:
|
60
|
+
self.theme = "textual-ansi"
|
61
|
+
self.viewer = self.query_one(VerticalScroll)
|
62
|
+
|
63
|
+
def action_scroll_down(self) -> None:
|
64
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + 1)
|
65
|
+
|
66
|
+
def action_scroll_up(self) -> None:
|
67
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y - 1)
|
68
|
+
|
69
|
+
def action_page_down(self) -> None:
|
70
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + self.viewer.virtual_size.height)
|
71
|
+
|
72
|
+
def action_page_up(self) -> None:
|
73
|
+
self.viewer.scroll_to(y=max(self.viewer.scroll_y - self.viewer.virtual_size.height, 0))
|
74
|
+
|
75
|
+
def action_half_page_down(self) -> None:
|
76
|
+
self.viewer.scroll_to(y=self.viewer.scroll_y + (self.viewer.virtual_size.height / 2))
|
77
|
+
|
78
|
+
def action_go_to_top(self) -> None:
|
79
|
+
self.viewer.scroll_to(y=0)
|
80
|
+
|
81
|
+
def action_go_to_bottom(self) -> None:
|
82
|
+
self.viewer.scroll_to(y=self.viewer.virtual_size.height)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nbcat
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.13.0
|
4
4
|
Summary: cat for jupyter notebooks
|
5
5
|
Project-URL: Homepage, https://github.com/akopdev/nbcat
|
6
6
|
Project-URL: Repository, https://github.com/akopdev/nbcat
|
@@ -33,6 +33,7 @@ Requires-Dist: argcomplete
|
|
33
33
|
Requires-Dist: pydantic
|
34
34
|
Requires-Dist: requests
|
35
35
|
Requires-Dist: rich
|
36
|
+
Requires-Dist: textual
|
36
37
|
Requires-Dist: timg
|
37
38
|
Provides-Extra: dev
|
38
39
|
Requires-Dist: pytest; extra == 'dev'
|
@@ -52,9 +53,10 @@ Description-Content-Type: text/markdown
|
|
52
53
|
|
53
54
|
## Features
|
54
55
|
|
55
|
-
- Very fast and lightweight with minimal dependencies
|
56
|
-
- Preview remote notebooks without downloading them
|
57
|
-
-
|
56
|
+
- Very fast and lightweight with minimal dependencies.
|
57
|
+
- Preview remote notebooks without downloading them.
|
58
|
+
- Enable paginated view mode with keyboard navigation (similar to `less`).
|
59
|
+
- Supports for all Jupyter notebook versions, including old legacy formats.
|
58
60
|
|
59
61
|
## Motivation
|
60
62
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
nbcat/__init__.py,sha256=DgpLNbv0e1LIEOOe54Db8_390i9pelMEFEnsBsNmyhA,23
|
2
|
+
nbcat/enums.py,sha256=Fn8PIcLl_uY4nQIs1EUvmKTwfhNUIZgmhRFiCSJk9wk,411
|
3
|
+
nbcat/exceptions.py,sha256=Ho7LQz9K70VtIMDNtAwuAtGmb-lFKxGxSj7MN3-EpDA,321
|
4
|
+
nbcat/image.py,sha256=hGZZK5mtij7ckWAvQwzim3thqGC92pLW5ZU5CYbRv_Q,995
|
5
|
+
nbcat/main.py,sha256=FSXD7SobpjhwDvOKAS1C-Lntmv9mPJhDUugjq8dBzAA,6678
|
6
|
+
nbcat/markdown.py,sha256=GkPNfzBhNLMl89pVcj14U6ytYUVk3yNB0G1zGYRRJ04,2962
|
7
|
+
nbcat/pager.py,sha256=Yu0XIh5MvhvT-cmULYVxo6s2Ufjf2CQ-NDS5fcMQ-IM,3184
|
8
|
+
nbcat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
nbcat/schemas.py,sha256=a7GoKgPTHgun199-J-sZq-ahkdQwvyRaCdQVg1gC798,3135
|
10
|
+
nbcat-0.13.0.dist-info/METADATA,sha256=rspE5gM8qznr1ZNL9REUdPBJho1QRlDRcXSTl2ngSH8,4265
|
11
|
+
nbcat-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
12
|
+
nbcat-0.13.0.dist-info/entry_points.txt,sha256=io_GRDsecAkYuCZALsjyea3VBq91VCoSznqlZEAJshY,42
|
13
|
+
nbcat-0.13.0.dist-info/licenses/LICENSE,sha256=7GjUnahXdd5opdvlpJdb1BisLbiXt2iOFhzIUduhdkE,1072
|
14
|
+
nbcat-0.13.0.dist-info/RECORD,,
|
nbcat-0.12.1.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
nbcat/__init__.py,sha256=PAuBI8I6F9Yu_86XjI2yaWn8QmCd9ZvK7tkZLWvEg-Q,23
|
2
|
-
nbcat/enums.py,sha256=Fn8PIcLl_uY4nQIs1EUvmKTwfhNUIZgmhRFiCSJk9wk,411
|
3
|
-
nbcat/exceptions.py,sha256=Ho7LQz9K70VtIMDNtAwuAtGmb-lFKxGxSj7MN3-EpDA,321
|
4
|
-
nbcat/image.py,sha256=hGZZK5mtij7ckWAvQwzim3thqGC92pLW5ZU5CYbRv_Q,995
|
5
|
-
nbcat/main.py,sha256=gZ8mM2louxU8GgB40F7DE7pc7MAidDHatiNjkLUzeug,5839
|
6
|
-
nbcat/markdown.py,sha256=GkPNfzBhNLMl89pVcj14U6ytYUVk3yNB0G1zGYRRJ04,2962
|
7
|
-
nbcat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
nbcat/schemas.py,sha256=a7GoKgPTHgun199-J-sZq-ahkdQwvyRaCdQVg1gC798,3135
|
9
|
-
nbcat-0.12.1.dist-info/METADATA,sha256=Jq7TL6gCnqsAn_hm5eTHHK-DRGbp3nXn4aq6-w_jv2Y,4164
|
10
|
-
nbcat-0.12.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
-
nbcat-0.12.1.dist-info/entry_points.txt,sha256=io_GRDsecAkYuCZALsjyea3VBq91VCoSznqlZEAJshY,42
|
12
|
-
nbcat-0.12.1.dist-info/licenses/LICENSE,sha256=7GjUnahXdd5opdvlpJdb1BisLbiXt2iOFhzIUduhdkE,1072
|
13
|
-
nbcat-0.12.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|