formulens 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.
- formulens-0.0.1/LICENSE +21 -0
- formulens-0.0.1/PKG-INFO +87 -0
- formulens-0.0.1/README.md +60 -0
- formulens-0.0.1/pyproject.toml +48 -0
- formulens-0.0.1/pyproject.toml.orig +38 -0
- formulens-0.0.1/src/formulens/__init__.py +7 -0
- formulens-0.0.1/src/formulens/cli.py +8 -0
- formulens-0.0.1/src/formulens/commands/__init__.py +1 -0
- formulens-0.0.1/src/formulens/commands/config.py +43 -0
- formulens-0.0.1/src/formulens/commands/errors.py +16 -0
- formulens-0.0.1/src/formulens/configuration/__init__.py +1 -0
- formulens-0.0.1/src/formulens/configuration/schema.py +12 -0
- formulens-0.0.1/src/formulens/configuration/storage.py +50 -0
formulens-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rajesh Das (rajeshdas.dev)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
formulens-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: formulens
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Local equation-to-LaTeX recognition with a Linux-first CLI.
|
|
5
|
+
Keywords: latex,equations,ocr,cli,linux,configuration
|
|
6
|
+
Author: Rajesh Das
|
|
7
|
+
Author-email: Rajesh Das <hyperoot.tech@proton.me>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
18
|
+
Requires-Dist: pydantic>=2.13.5
|
|
19
|
+
Requires-Dist: typer>=0.27.2
|
|
20
|
+
Requires-Dist: utilityhub-config>=0.2.7
|
|
21
|
+
Requires-Python: >=3.14
|
|
22
|
+
Project-URL: Homepage, https://formulens.hyperoot.dev/
|
|
23
|
+
Project-URL: Documentation, https://formulens.hyperoot.dev/
|
|
24
|
+
Project-URL: Repository, https://github.com/HYP3R00T/formulens
|
|
25
|
+
Project-URL: Issues, https://github.com/HYP3R00T/formulens/issues
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# Formulens
|
|
29
|
+
|
|
30
|
+
Formulens is a Linux-first CLI for a local equation-to-LaTeX workflow.
|
|
31
|
+
|
|
32
|
+
Version **0.0.1** provides configuration management through Typer and UtilityHub
|
|
33
|
+
Config. Equation recognition, screen capture, daemon mode, and clipboard
|
|
34
|
+
integration are not implemented in this release.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
Requires Python **3.14 or newer**. After this release is published, install it with
|
|
39
|
+
[uv](https://docs.astral.sh/uv/):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv tool install formulens
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Configuration
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
formulens --help
|
|
49
|
+
formulens config init
|
|
50
|
+
formulens config path
|
|
51
|
+
formulens config show
|
|
52
|
+
formulens config set notifications false
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Settings are stored at `~/.config/formulens/formulens.toml`:
|
|
56
|
+
|
|
57
|
+
```toml
|
|
58
|
+
copy_to_clipboard = true
|
|
59
|
+
notifications = true
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`init` preserves existing configuration. `path` prints its location. `show`
|
|
63
|
+
displays effective settings as JSON without creating files. `set` validates and
|
|
64
|
+
saves an edit. These preferences are stored for future desktop integration;
|
|
65
|
+
they do not yet trigger clipboard output or notifications.
|
|
66
|
+
|
|
67
|
+
Environment variables such as `FORMULENS_NOTIFICATIONS=false` override saved
|
|
68
|
+
values. Formulens loads global TOML/YAML configuration and any `.env` inside its
|
|
69
|
+
configuration directory, without searching the current working directory.
|
|
70
|
+
`set` updates only the TOML file and does not save environment overrides.
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
From a checkout of the repository:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv sync --all-packages
|
|
78
|
+
uv run formulens --help
|
|
79
|
+
uv run python -m unittest discover -s tests
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
See the [project repository](https://github.com/HYP3R00T/formulens) for development
|
|
83
|
+
setup and documentation.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT. Copyright 2026 Rajesh Das. The license is included in the distribution.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Formulens
|
|
2
|
+
|
|
3
|
+
Formulens is a Linux-first CLI for a local equation-to-LaTeX workflow.
|
|
4
|
+
|
|
5
|
+
Version **0.0.1** provides configuration management through Typer and UtilityHub
|
|
6
|
+
Config. Equation recognition, screen capture, daemon mode, and clipboard
|
|
7
|
+
integration are not implemented in this release.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Requires Python **3.14 or newer**. After this release is published, install it with
|
|
12
|
+
[uv](https://docs.astral.sh/uv/):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
uv tool install formulens
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Configuration
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
formulens --help
|
|
22
|
+
formulens config init
|
|
23
|
+
formulens config path
|
|
24
|
+
formulens config show
|
|
25
|
+
formulens config set notifications false
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Settings are stored at `~/.config/formulens/formulens.toml`:
|
|
29
|
+
|
|
30
|
+
```toml
|
|
31
|
+
copy_to_clipboard = true
|
|
32
|
+
notifications = true
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`init` preserves existing configuration. `path` prints its location. `show`
|
|
36
|
+
displays effective settings as JSON without creating files. `set` validates and
|
|
37
|
+
saves an edit. These preferences are stored for future desktop integration;
|
|
38
|
+
they do not yet trigger clipboard output or notifications.
|
|
39
|
+
|
|
40
|
+
Environment variables such as `FORMULENS_NOTIFICATIONS=false` override saved
|
|
41
|
+
values. Formulens loads global TOML/YAML configuration and any `.env` inside its
|
|
42
|
+
configuration directory, without searching the current working directory.
|
|
43
|
+
`set` updates only the TOML file and does not save environment overrides.
|
|
44
|
+
|
|
45
|
+
## Development
|
|
46
|
+
|
|
47
|
+
From a checkout of the repository:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv sync --all-packages
|
|
51
|
+
uv run formulens --help
|
|
52
|
+
uv run python -m unittest discover -s tests
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See the [project repository](https://github.com/HYP3R00T/formulens) for development
|
|
56
|
+
setup and documentation.
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT. Copyright 2026 Rajesh Das. The license is included in the distribution.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "formulens"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "Local equation-to-LaTeX recognition with a Linux-first CLI."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
keywords = [
|
|
10
|
+
"latex",
|
|
11
|
+
"equations",
|
|
12
|
+
"ocr",
|
|
13
|
+
"cli",
|
|
14
|
+
"linux",
|
|
15
|
+
"configuration",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Environment :: Console",
|
|
20
|
+
"Intended Audience :: Science/Research",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"pydantic>=2.13.5",
|
|
29
|
+
"typer>=0.27.2",
|
|
30
|
+
"utilityhub-config>=0.2.7",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[[project.authors]]
|
|
34
|
+
name = "Rajesh Das"
|
|
35
|
+
email = "hyperoot.tech@proton.me"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
formulens = "formulens:main"
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://formulens.hyperoot.dev/"
|
|
42
|
+
Documentation = "https://formulens.hyperoot.dev/"
|
|
43
|
+
Repository = "https://github.com/HYP3R00T/formulens"
|
|
44
|
+
Issues = "https://github.com/HYP3R00T/formulens/issues"
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["uv_build>=0.12.7,<0.13.0"]
|
|
48
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "formulens"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "Local equation-to-LaTeX recognition with a Linux-first CLI."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Rajesh Das", email = "hyperoot.tech@proton.me" }]
|
|
10
|
+
keywords = ["latex", "equations", "ocr", "cli", "linux", "configuration"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"Operating System :: POSIX :: Linux",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Programming Language :: Python :: 3.14",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"pydantic>=2.13.5",
|
|
23
|
+
"typer>=0.27.2",
|
|
24
|
+
"utilityhub-config>=0.2.7",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
formulens = "formulens:main"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://formulens.hyperoot.dev/"
|
|
32
|
+
Documentation = "https://formulens.hyperoot.dev/"
|
|
33
|
+
Repository = "https://github.com/HYP3R00T/formulens"
|
|
34
|
+
Issues = "https://github.com/HYP3R00T/formulens/issues"
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["uv_build>=0.12.7,<0.13.0"]
|
|
38
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI command groups and presentation helpers."""
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Commands for managing Formulens configuration."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from formulens.commands.errors import run_config_action
|
|
8
|
+
from formulens.configuration.storage import (
|
|
9
|
+
get_settings_path,
|
|
10
|
+
initialize_settings,
|
|
11
|
+
load_configuration,
|
|
12
|
+
set_setting,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
app = typer.Typer(help="Manage configuration in ~/.config/formulens.", no_args_is_help=True)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@app.command("init")
|
|
19
|
+
def config_init() -> None:
|
|
20
|
+
"""Create default configuration, preserving any existing settings."""
|
|
21
|
+
typer.echo(run_config_action(initialize_settings))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@app.command("path")
|
|
25
|
+
def config_path() -> None:
|
|
26
|
+
"""Print the configuration path without creating a file."""
|
|
27
|
+
typer.echo(get_settings_path())
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@app.command("show")
|
|
31
|
+
def config_show() -> None:
|
|
32
|
+
"""Print effective settings as JSON, including environment overrides."""
|
|
33
|
+
settings = run_config_action(load_configuration)
|
|
34
|
+
typer.echo(settings.model_dump_json(indent=2))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@app.command("set")
|
|
38
|
+
def config_set(
|
|
39
|
+
key: Annotated[str, typer.Argument(help="Setting name, such as notifications.")],
|
|
40
|
+
value: Annotated[str, typer.Argument(help="New value: true or false.")],
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Validate and save a setting in the global TOML file."""
|
|
43
|
+
typer.echo(run_config_action(lambda: set_setting(key, value)))
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Translate configuration failures into CLI errors."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from pydantic import ValidationError
|
|
7
|
+
from utilityhub_config.errors import ConfigError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def run_config_action[T](action: Callable[[], T]) -> T:
|
|
11
|
+
"""Report configuration failures without a Python traceback."""
|
|
12
|
+
try:
|
|
13
|
+
return action()
|
|
14
|
+
except (ConfigError, ValidationError, OSError, ValueError, RuntimeError) as error:
|
|
15
|
+
typer.echo(f"Configuration error: {error}", err=True)
|
|
16
|
+
raise typer.Exit(code=1) from error
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Typed settings and persistence, independent of the CLI."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Validated Formulens preferences."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Settings(BaseModel):
|
|
7
|
+
"""Preferences for clipboard output and desktop notifications."""
|
|
8
|
+
|
|
9
|
+
model_config = ConfigDict(extra="forbid")
|
|
10
|
+
|
|
11
|
+
copy_to_clipboard: bool = True
|
|
12
|
+
notifications: bool = True
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Load and save user configuration through UtilityHub Config."""
|
|
2
|
+
|
|
3
|
+
import tomllib
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from utilityhub_config import ensure_config_file, get_config_path, load_settings, write_config
|
|
7
|
+
|
|
8
|
+
from formulens.configuration.schema import Settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_settings_path() -> Path:
|
|
12
|
+
return get_config_path("formulens")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def initialize_settings() -> Path:
|
|
16
|
+
"""Create defaults without overwriting an existing configuration."""
|
|
17
|
+
path = get_settings_path()
|
|
18
|
+
if path.exists():
|
|
19
|
+
read_saved_settings()
|
|
20
|
+
return ensure_config_file(Settings(), "formulens")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def read_saved_settings() -> Settings:
|
|
24
|
+
"""Read only persisted values, so edits never save environment overrides."""
|
|
25
|
+
path = get_settings_path()
|
|
26
|
+
if not path.exists():
|
|
27
|
+
return Settings()
|
|
28
|
+
with path.open("rb") as stream:
|
|
29
|
+
return Settings.model_validate(tomllib.load(stream))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def load_configuration() -> Settings:
|
|
33
|
+
"""Resolve settings without discovering files in the current directory."""
|
|
34
|
+
settings, _ = load_settings(
|
|
35
|
+
Settings,
|
|
36
|
+
app_name="formulens",
|
|
37
|
+
cwd=get_settings_path().parent,
|
|
38
|
+
env_prefix="FORMULENS",
|
|
39
|
+
)
|
|
40
|
+
return settings
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def set_setting(key: str, value: str) -> Path:
|
|
44
|
+
"""Validate a single edit before writing the saved configuration."""
|
|
45
|
+
if key not in Settings.model_fields:
|
|
46
|
+
raise ValueError(f"Unknown setting '{key}'. Choose from: {', '.join(Settings.model_fields)}")
|
|
47
|
+
values = read_saved_settings().model_dump()
|
|
48
|
+
values[key] = value
|
|
49
|
+
settings = Settings.model_validate(values)
|
|
50
|
+
return write_config(settings, "formulens")
|