mdview-tui 0.0.1__tar.gz

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.
@@ -0,0 +1,31 @@
1
+ Metadata-Version: 2.3
2
+ Name: mdview-tui
3
+ Version: 0.0.1
4
+ Summary: CLI tool to view markdown files in the terminal.
5
+ Author: Shunichiro Nomura
6
+ Author-email: Shunichiro Nomura <nomura@space.t.u-tokyo.ac.jp>
7
+ Classifier: Programming Language :: Python
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Programming Language :: Python :: 3.14
10
+ Classifier: Typing :: Typed
11
+ Requires-Dist: rich>=14.3.3
12
+ Requires-Dist: textual[syntax]>=8.2.2
13
+ Requires-Dist: typer>=0.24.1
14
+ Requires-Python: >=3.14
15
+ Description-Content-Type: text/markdown
16
+
17
+ # mdview
18
+
19
+ This is a thin wrapper around Textual's Markdown widget to view markdown files in the terminal.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ uv tool install mdview-tui
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```bash
30
+ mdview <markdown-file>
31
+ ```
@@ -0,0 +1,15 @@
1
+ # mdview
2
+
3
+ This is a thin wrapper around Textual's Markdown widget to view markdown files in the terminal.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ uv tool install mdview-tui
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ mdview <markdown-file>
15
+ ```
@@ -0,0 +1,113 @@
1
+ [project]
2
+ name = "mdview-tui"
3
+ version = "0.0.1"
4
+ description = "CLI tool to view markdown files in the terminal."
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ authors = [
8
+ { name = "Shunichiro Nomura", email = "nomura@space.t.u-tokyo.ac.jp" },
9
+ ]
10
+ classifiers = [
11
+ "Programming Language :: Python",
12
+ "Programming Language :: Python :: 3 :: Only",
13
+ "Programming Language :: Python :: 3.14",
14
+ "Typing :: Typed",
15
+ ]
16
+ dependencies = [
17
+ "rich>=14.3.3",
18
+ "textual[syntax]>=8.2.2",
19
+ "typer>=0.24.1",
20
+ ]
21
+
22
+ [project.scripts]
23
+ mdview = "mdview_tui:main"
24
+
25
+ [dependency-groups]
26
+ dev = [
27
+ "pre-commit>=4.2.0",
28
+ { include-group = "ruff" },
29
+ { include-group = "test" },
30
+ { include-group = "typing" },
31
+ ]
32
+ ruff = ["ruff>=0.11.13"]
33
+ test = [
34
+ "pytest>=9.0.0",
35
+ # "coverage>=7.8.2", # If you use coverage
36
+ ]
37
+ typing = [
38
+ "basedpyright>=1.36.2",
39
+ "mypy>=1.16.1",
40
+ "ty>=0.0.8",
41
+ { include-group = "test" },
42
+ ]
43
+
44
+ [build-system]
45
+ requires = ["uv_build>=0.11,<0.12"]
46
+ build-backend = "uv_build"
47
+
48
+ [tool.mypy]
49
+ strict = true
50
+
51
+ [tool.pytest]
52
+ addopts = [
53
+ "--capture=no",
54
+ "--color=yes",
55
+ "--log-cli-level=INFO",
56
+ "--strict-markers",
57
+ "--verbose",
58
+ "--verbose",
59
+ "-ra", # show extra test summary info for all tests except passed tests
60
+ ]
61
+ minversion = "9.0"
62
+ testpaths = ["tests"]
63
+
64
+ [tool.ruff]
65
+ line-length = 120
66
+
67
+ [tool.ruff.lint]
68
+ select = ["ALL"]
69
+ # Modify the following rules according to your preferences
70
+ ignore = [
71
+ # "PLR2004", # magic numbers
72
+ "S101", # use of assert
73
+ "G", # logging format
74
+ # "ANN101", # missing type annotation for self in method
75
+ # "ANN102", # missing type annotation for cls in classmethod
76
+ # "D100", # missing docstring in public module
77
+ # "D101", # missing docstring in public class
78
+ # "D102", # missing docstring in public method
79
+ # "D103", # missing docstring in public function
80
+ # "D104", # missing docstring in public package
81
+ # "D105", # missing docstring in magic method
82
+ # "D107", # missing docstring in __init__
83
+ "D203", # 1 blank line required before class docstring
84
+ "D213", # multi-line docstring summary should start at the second line
85
+ # "PGH003", # Use specific rule codes when ignoring type issues
86
+ # "RET505", # Unnecessary `else` after `return` statement
87
+ "ANN401", # Dynamically typed expressions (typing.Any) are disallowed
88
+ # "D401", # First line should be in imperative mood
89
+ "TD002", # Missing author in TODO
90
+ "TD003", # add link on issue into TODO
91
+ # "PLR0913", # Too many arguments to function call
92
+ # "D407", # Missing dashed underline after section
93
+ # "ERA001", # Commented out code
94
+ "FIX002", # Fixme comment
95
+ # "S311", # suspicious-non-cryptographic-random-usage
96
+ # "EM101", # raw-string-in-exception
97
+ # "TRY003", # Avoid specifying long messages outside the exception class
98
+ # "UP040", # uses `TypeAlias` annotation instead of the `type` keyword. This is to be compatible with griffe.
99
+ ]
100
+ unfixable = [
101
+ "F401", # Prevent auto-fix for unused imports
102
+ ]
103
+
104
+ [tool.ruff.lint.per-file-ignores]
105
+ "tests/**.py" = [
106
+ "D", # Docstring
107
+ "INP001", # implicit-namespace-package
108
+ "ANN201", # missing-return-type-undocumented-public-function
109
+ "S101", # use of assert
110
+ ]
111
+
112
+ [tool.uv]
113
+ exclude-newer = "7 days"
@@ -0,0 +1,33 @@
1
+ """mdview_tui is a terminal-based markdown viewer built with Textual."""
2
+
3
+ from pathlib import Path # noqa: TC003
4
+ from typing import Annotated
5
+
6
+ import typer
7
+ from rich.console import Console
8
+
9
+ from .app import MarkdownViewerApp
10
+
11
+ err_console = Console(stderr=True)
12
+
13
+
14
+ def _main(
15
+ file: Annotated[
16
+ Path,
17
+ typer.Argument(help="Path to the markdown file to view."),
18
+ ],
19
+ ) -> None:
20
+ """View markdown files in the terminal."""
21
+ if not file.exists():
22
+ err_console.print(f"[bold red]Error:[/] File not found: [yellow]{file}[/]")
23
+ raise typer.Exit(code=1)
24
+ if not file.is_file():
25
+ err_console.print(f"[bold red]Error:[/] Not a file: [yellow]{file}[/]")
26
+ raise typer.Exit(code=1)
27
+ text = file.read_text()
28
+ MarkdownViewerApp(text, title=str(file)).run()
29
+
30
+
31
+ def main() -> None:
32
+ """Entry point for the mdview_tui application."""
33
+ typer.run(_main)
@@ -0,0 +1,37 @@
1
+ """MarkdownViewerApp Textual application for viewing markdown content in the terminal."""
2
+
3
+ from textual.app import App, ComposeResult
4
+ from textual.binding import Binding
5
+ from textual.widgets import Footer, Markdown
6
+
7
+
8
+ class MarkdownViewerApp(App):
9
+ """A Textual application for viewing markdown content in the terminal."""
10
+
11
+ BINDINGS = [ # noqa: RUF012
12
+ Binding("q", "quit", "Quit"),
13
+ ]
14
+
15
+ CSS = """
16
+ Markdown {
17
+ layout: stream;
18
+ padding: 0 2;
19
+ }
20
+ """
21
+
22
+ theme = "tokyo-night"
23
+
24
+ def __init__(self, text: str, title: str = "Markdown") -> None:
25
+ """Initialize the MarkdownViewerApp with the given markdown text and title."""
26
+ super().__init__()
27
+ self._text = text
28
+ self._title = title
29
+
30
+ def compose(self) -> ComposeResult:
31
+ """Compose the UI components for the application."""
32
+ yield Markdown(self._text)
33
+ yield Footer()
34
+
35
+ def on_mount(self) -> None:
36
+ """Set the application title on mount."""
37
+ self.title = self._title