diff --git a/home/base/tui/editors/README.md b/home/base/tui/editors/README.md index fe9e7125..4a6db4b8 100644 --- a/home/base/tui/editors/README.md +++ b/home/base/tui/editors/README.md @@ -7,5 +7,5 @@ closure. Editor programs, keymaps, `$EDITOR` defaults, and usage docs live under [`../../core/editors/`](../../core/editors/README.md) (Helix, Neovim backup, glossary, cheatsheets). -[`default.nix`](./default.nix) imports `./packages.nix` so `home/base/tui` can keep pulling in -tooling without mixing it into `core/editors`. +[`default.nix`](./default.nix) imports [`ipython/`](./ipython/) and `./packages.nix` so +`home/base/tui` can keep pulling in tooling without mixing it into `core/editors`. diff --git a/home/base/tui/editors/default.nix b/home/base/tui/editors/default.nix index 02f768d1..33c5c7fe 100644 --- a/home/base/tui/editors/default.nix +++ b/home/base/tui/editors/default.nix @@ -1,4 +1,7 @@ # Editor-related language servers and heavy tooling — kept out of `core/editors`. { - imports = [ ./packages.nix ]; + imports = [ + ./ipython + ./packages.nix + ]; } diff --git a/home/base/tui/editors/ipython/README.md b/home/base/tui/editors/ipython/README.md new file mode 100644 index 00000000..89cf1930 --- /dev/null +++ b/home/base/tui/editors/ipython/README.md @@ -0,0 +1,13 @@ +# IPython + +[`default.nix`](./default.nix) manages `~/.ipython/profile_default` with two pieces: + +- `ipython_config.py` disables SQLite history because interactive sessions may contain secrets. +- `startup/10-data-helpers.py` loads JSON, YAML, TOML, and CSV helpers at every IPython start. It + also pre-imports a small set of common standard-library names such as `Path`, `Counter`, and + `datetime`. + +[`data-helpers.py`](./data-helpers.py) deliberately keeps heavier libraries such as NumPy and pandas +out of startup; import them explicitly when needed. The `~/.ipython` profile is not persisted by +`hosts/idols-ai/preservation.nix`, so Home Manager recreates the config and helpers from the Nix +store on every activation. diff --git a/home/base/tui/editors/ipython/data-helpers.py b/home/base/tui/editors/ipython/data-helpers.py new file mode 100644 index 00000000..b02a5d78 --- /dev/null +++ b/home/base/tui/editors/ipython/data-helpers.py @@ -0,0 +1,102 @@ +# ruff: noqa: F401 +"""IPython startup helpers for inspecting structured data. + +IPython executes files in this profile's startup directory before the first +prompt, so these helpers are available in every interactive session. +""" + +# A small set of common names preloaded for interactive use. The unused-import +# exception is intentional: IPython exposes these names directly in the prompt. +import csv +import io +import json +import os +import re +import shutil +import subprocess +import sys +import tomllib +from collections import Counter, defaultdict +from datetime import date, datetime, timedelta, timezone +from pathlib import Path +from pprint import pprint + +import toml +import yaml + + +def loads_json(text: str): + return json.loads(text) + + +def dumps_json(value, indent: int = 2) -> str: + return json.dumps(value, ensure_ascii=False, indent=indent) + + +def loads_yaml(text: str): + return yaml.safe_load(text) + + +def dumps_yaml(value) -> str: + return yaml.safe_dump(value, allow_unicode=True, sort_keys=False) + + +def loads_toml(text: str): + return tomllib.loads(text) + + +def dumps_toml(value) -> str: + return toml.dumps(value) + + +def loads_csv(text: str) -> list[dict[str, str]]: + return list(csv.DictReader(io.StringIO(text))) + + +def dumps_csv(rows, fieldnames=None) -> str: + rows = list(rows) + if not rows: + return "" + + fieldnames = fieldnames or list(rows[0]) + buffer = io.StringIO(newline="") + writer = csv.DictWriter(buffer, fieldnames=fieldnames) + writer.writeheader() + writer.writerows(rows) + return buffer.getvalue() + + +def show(value): + """Pretty-print a value and return it for further use.""" + pprint(value, width=120, sort_dicts=False) + return value + + +def show_json(text: str): + return show(loads_json(text)) + + +def show_yaml(text: str): + return show(loads_yaml(text)) + + +def show_toml(text: str): + return show(loads_toml(text)) + + +def show_csv(text: str): + return show(loads_csv(text)) + + +def copy_to_clipboard(text: str) -> str: + """Copy text to the system clipboard and return it.""" + commands = ( + [["pbcopy"]] + if sys.platform == "darwin" + else [["wl-copy"], ["xclip", "-selection", "clipboard"]] + ) + for command in commands: + if shutil.which(command[0]): + subprocess.run(command, input=text, text=True, check=True) + return text + raise RuntimeError("No clipboard command found (need wl-copy, xclip, or pbcopy)") diff --git a/home/base/tui/editors/ipython/default.nix b/home/base/tui/editors/ipython/default.nix new file mode 100644 index 00000000..366413b8 --- /dev/null +++ b/home/base/tui/editors/ipython/default.nix @@ -0,0 +1,14 @@ +{ ... }: +{ + # Interactive IPython sessions routinely handle credentials and other + # sensitive values, so keep the SQLite history disabled rather than relying + # on the profile directory's lifetime. Home Manager recreates these files + # from the Nix store on every activation. + home.file = { + ".ipython/profile_default/ipython_config.py".text = '' + c = get_config() + c.HistoryManager.enabled = False + ''; + ".ipython/profile_default/startup/10-data-helpers.py".source = ./data-helpers.py; + }; +} diff --git a/home/base/tui/editors/packages.nix b/home/base/tui/editors/packages.nix index 2c83eb0b..f7df728a 100644 --- a/home/base/tui/editors/packages.nix +++ b/home/base/tui/editors/packages.nix @@ -71,6 +71,7 @@ requests pyquery pyyaml + toml # TOML writing; reading uses stdlib tomllib protobuf # protocol buffer compiler ] )) diff --git a/hosts/idols-ai/preservation.nix b/hosts/idols-ai/preservation.nix index 506378e9..46ae5bcd 100644 --- a/hosts/idols-ai/preservation.nix +++ b/hosts/idols-ai/preservation.nix @@ -216,7 +216,10 @@ in ".config/Joplin" # joplin-desktop ".local/share/jupyter" - ".ipython" + # Deliberately not persisted: ~/.ipython contains history.sqlite, and + # interactive sessions may contain credentials or other sensitive + # values. Home Manager recreates the profile config and startup helpers + # from the Nix store on every activation. # ====================================== # Cloud Native