omdev 0.0.0.dev293__tar.gz → 0.0.0.dev295__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.
- {omdev-0.0.0.dev293/omdev.egg-info → omdev-0.0.0.dev295}/PKG-INFO +4 -2
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/.manifests.json +1 -1
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/__about__.py +1 -1
- omdev-0.0.0.dev295/omdev/ptk/markdown/LICENSE +22 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/__init__.py +2 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/__main__.py +4 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/border.py +94 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/cli.py +30 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/markdown.py +384 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/parser.py +42 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/styles.py +29 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/tags.py +298 -0
- omdev-0.0.0.dev295/omdev/ptk/markdown/utils.py +365 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/doc.py +3 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295/omdev.egg-info}/PKG-INFO +4 -2
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev.egg-info/SOURCES.txt +10 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev.egg-info/requires.txt +3 -1
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/pyproject.toml +4 -2
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/LICENSE +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/README.md +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/gen.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/imports.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/main.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/manifests.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/resources.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/srcfiles.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/strip.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/types.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/amalg/typing.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cc/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cc/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cc/cdeps.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cc/cdeps.toml +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cc/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/ci.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/compose.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/consts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/buildcaching.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/cacheserved/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/cacheserved/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/cacheserved/manifests.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/cmds.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/dataserver.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/imagepulling.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/packing.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/repositories.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/docker/utils.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/clients.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v1/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v1/api.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v1/client.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v2/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v2/api.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v2/azure.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/api/v2/client.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/bootstrap.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/cache.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/env.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/github/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/requirements.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/shell.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ci/utils.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/handlers.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/http.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/routes.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/server.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/dataserver/targets.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/git/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/git/magic.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/git/shallow.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/home/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/home/paths.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/home/secrets.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/home/shadow.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/default.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/pyenv/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/pyenv/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/pyenv/install.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/pyenv/provider.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/pyenv/pyenv.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/uv/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/uv/provider.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/manifests/dumping.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/building.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/compression.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/data.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/datarefs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/dataserver.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/loading.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/media.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/pack/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/pack/packing.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/pack/repositories.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/pack/unpacking.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/repositories.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/oci/tars.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/revisions.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/packaging/wheelfile.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/caches.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/imports.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ptk/apps/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/attrdocs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/bracepy.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/classdot.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/findimports.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/scripts/execstat.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/srcheaders.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/tools/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/tools/importscan.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/py/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/resources/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/resources/docker-dev.sh +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/resources/python.sh +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/ci.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tagstrings.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tokens/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tokens/all.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tokens/tokenizert.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tokens/utils.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/diff.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/git/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/git/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/git/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/git/consts.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/git/messages.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/intellij.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/linehisto.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/mkenv.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/shadow.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev293 → omdev-0.0.0.dev295}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev295
|
4
4
|
Summary: omdev
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,13 +12,14 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omlish==0.0.0.dev295
|
16
16
|
Provides-Extra: all
|
17
17
|
Requires-Dist: black~=25.1; extra == "all"
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
19
19
|
Requires-Dist: pcpp~=1.30; extra == "all"
|
20
20
|
Requires-Dist: docutils~=0.21; extra == "all"
|
21
21
|
Requires-Dist: markdown-it-py~=3.0; extra == "all"
|
22
|
+
Requires-Dist: mdit-py-plugins~=0.4; extra == "all"
|
22
23
|
Requires-Dist: mypy~=1.15; extra == "all"
|
23
24
|
Requires-Dist: gprof2dot~=2025.4; extra == "all"
|
24
25
|
Requires-Dist: prompt-toolkit~=3.0; extra == "all"
|
@@ -31,6 +32,7 @@ Requires-Dist: pcpp~=1.30; extra == "c"
|
|
31
32
|
Provides-Extra: doc
|
32
33
|
Requires-Dist: docutils~=0.21; extra == "doc"
|
33
34
|
Requires-Dist: markdown-it-py~=3.0; extra == "doc"
|
35
|
+
Requires-Dist: mdit-py-plugins~=0.4; extra == "doc"
|
34
36
|
Provides-Extra: mypy
|
35
37
|
Requires-Dist: mypy~=1.15; extra == "mypy"
|
36
38
|
Provides-Extra: prof
|
@@ -0,0 +1,22 @@
|
|
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.
|
@@ -0,0 +1,94 @@
|
|
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 = '┛'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import argparse
|
2
|
+
import sys
|
3
|
+
|
4
|
+
from ... import ptk
|
5
|
+
from .markdown import Markdown
|
6
|
+
from .styles import MARKDOWN_STYLE
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
|
11
|
+
|
12
|
+
def _main() -> None:
|
13
|
+
parser = argparse.ArgumentParser()
|
14
|
+
parser.add_argument('file', nargs='?')
|
15
|
+
args = parser.parse_args()
|
16
|
+
|
17
|
+
if args.file is not None:
|
18
|
+
with open(args.file) as f:
|
19
|
+
src = f.read()
|
20
|
+
else:
|
21
|
+
src = sys.stdin.read()
|
22
|
+
|
23
|
+
ptk.print_formatted_text(
|
24
|
+
Markdown(src),
|
25
|
+
style=ptk.Style(list(MARKDOWN_STYLE)),
|
26
|
+
)
|
27
|
+
|
28
|
+
|
29
|
+
if __name__ == '__main__':
|
30
|
+
_main()
|
@@ -0,0 +1,384 @@
|
|
1
|
+
import itertools
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from ... import ptk
|
5
|
+
from .border import Border
|
6
|
+
from .border import SquareBorder
|
7
|
+
from .parser import markdown_parser
|
8
|
+
from .tags import TAG_INSETS
|
9
|
+
from .tags import TAG_RULES
|
10
|
+
from .utils import FormattedTextAlign
|
11
|
+
from .utils import align
|
12
|
+
from .utils import apply_style
|
13
|
+
from .utils import last_line_length
|
14
|
+
from .utils import lex
|
15
|
+
from .utils import strip
|
16
|
+
from .utils import wrap
|
17
|
+
|
18
|
+
|
19
|
+
if ta.TYPE_CHECKING:
|
20
|
+
from markdown_it.token import Token
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
_SIDES = {
|
27
|
+
'left': FormattedTextAlign.LEFT,
|
28
|
+
'right': FormattedTextAlign.RIGHT,
|
29
|
+
'center': FormattedTextAlign.CENTER,
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
class Markdown:
|
34
|
+
"""A markdown formatted text renderer. Accepts a markdown string and renders it at a given width."""
|
35
|
+
|
36
|
+
def __init__(
|
37
|
+
self,
|
38
|
+
markup: str,
|
39
|
+
width: int | None = None,
|
40
|
+
strip_trailing_lines: bool = True,
|
41
|
+
) -> None:
|
42
|
+
"""
|
43
|
+
Initialize the markdown formatter.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
markup: The markdown text to render
|
47
|
+
width: The width in characters available for rendering. If :py:const:`None` the terminal width will be used
|
48
|
+
strip_trailing_lines: If :py:const:`True`, empty lines at the end of the rendered output will be removed
|
49
|
+
"""
|
50
|
+
|
51
|
+
super().__init__()
|
52
|
+
|
53
|
+
self.markup = markup
|
54
|
+
self.width = width or ptk.get_app_session().output.get_size().columns
|
55
|
+
self.strip_trailing_lines = strip_trailing_lines
|
56
|
+
|
57
|
+
if (parser := markdown_parser()) is not None:
|
58
|
+
self.formatted_text = self.render(
|
59
|
+
tokens=parser.parse(self.markup),
|
60
|
+
width=self.width,
|
61
|
+
)
|
62
|
+
else:
|
63
|
+
self.formatted_text = lex(
|
64
|
+
ptk.to_formatted_text(self.markup),
|
65
|
+
lexer_name='markdown',
|
66
|
+
)
|
67
|
+
|
68
|
+
if strip_trailing_lines:
|
69
|
+
self.formatted_text = strip(
|
70
|
+
self.formatted_text,
|
71
|
+
left=False,
|
72
|
+
char='\n',
|
73
|
+
)
|
74
|
+
|
75
|
+
def render(
|
76
|
+
self,
|
77
|
+
tokens: ta.Sequence['Token'],
|
78
|
+
width: int = 80,
|
79
|
+
left: int = 0,
|
80
|
+
) -> ptk.StyleAndTextTuples:
|
81
|
+
"""
|
82
|
+
Render a list of parsed markdown tokens.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
tokens: The list of parsed tokens to render
|
86
|
+
width: The width at which to render the tokens
|
87
|
+
left: The position on the current line at which to render the output - used to indent subsequent lines when
|
88
|
+
rendering inline blocks like images
|
89
|
+
Returns:
|
90
|
+
Formatted text
|
91
|
+
"""
|
92
|
+
|
93
|
+
ft = []
|
94
|
+
|
95
|
+
i = 0
|
96
|
+
while i < len(tokens):
|
97
|
+
token = tokens[i]
|
98
|
+
|
99
|
+
# If this is an inline block, render it's children
|
100
|
+
if token.type == 'inline' and token.children:
|
101
|
+
ft += self.render(token.children, width)
|
102
|
+
i += 1
|
103
|
+
|
104
|
+
# Otherwise gather the tokens in the current block
|
105
|
+
else:
|
106
|
+
nest = 0
|
107
|
+
tokens_in_block = 0
|
108
|
+
for j, token in enumerate(tokens[i:]):
|
109
|
+
nest += token.nesting
|
110
|
+
if nest == 0:
|
111
|
+
tokens_in_block = j
|
112
|
+
break
|
113
|
+
|
114
|
+
# If there is a special method for rendering the block, use it
|
115
|
+
|
116
|
+
# Table require a lot of care
|
117
|
+
if token.tag == 'table':
|
118
|
+
ft += self.render_table(
|
119
|
+
tokens[i:i + tokens_in_block + 1],
|
120
|
+
width=width,
|
121
|
+
left=last_line_length(ft),
|
122
|
+
)
|
123
|
+
|
124
|
+
# We need to keep track of item numbers in ordered lists
|
125
|
+
elif token.tag == 'ol':
|
126
|
+
ft += self.render_ordered_list(
|
127
|
+
tokens[i:i + tokens_in_block + 1],
|
128
|
+
width=width,
|
129
|
+
left=last_line_length(ft),
|
130
|
+
)
|
131
|
+
|
132
|
+
# Otherwise all other blocks are rendered in the same way
|
133
|
+
else:
|
134
|
+
ft += self.render_block(
|
135
|
+
tokens[i:i + tokens_in_block + 1],
|
136
|
+
width=width,
|
137
|
+
left=last_line_length(ft),
|
138
|
+
)
|
139
|
+
|
140
|
+
i += j + 1
|
141
|
+
|
142
|
+
return ft
|
143
|
+
|
144
|
+
def render_block(
|
145
|
+
self,
|
146
|
+
tokens: ta.Sequence['Token'],
|
147
|
+
width: int,
|
148
|
+
left: int = 0,
|
149
|
+
) -> ptk.StyleAndTextTuples:
|
150
|
+
"""
|
151
|
+
Render a list of parsed markdown tokens representing a block element.
|
152
|
+
|
153
|
+
Args:
|
154
|
+
tokens: The list of parsed tokens to render
|
155
|
+
width: The width at which to render the tokens
|
156
|
+
left: The position on the current line at which to render the output - used to indent subsequent lines when
|
157
|
+
rendering inline blocks like images
|
158
|
+
Returns:
|
159
|
+
Formatted text
|
160
|
+
"""
|
161
|
+
|
162
|
+
ft = []
|
163
|
+
token = tokens[0]
|
164
|
+
|
165
|
+
# Restrict width if necessary
|
166
|
+
inset = TAG_INSETS.get(token.tag)
|
167
|
+
if inset:
|
168
|
+
width -= inset
|
169
|
+
|
170
|
+
style = 'class:md'
|
171
|
+
if token.tag:
|
172
|
+
style = f'{style}.{token.tag}'
|
173
|
+
|
174
|
+
# Render innards
|
175
|
+
if len(tokens) > 1:
|
176
|
+
ft += self.render(tokens[1:-1], width)
|
177
|
+
ft = apply_style(ft, style)
|
178
|
+
else:
|
179
|
+
ft.append((style, token.content))
|
180
|
+
|
181
|
+
# Apply tag rule
|
182
|
+
rule = TAG_RULES.get(token.tag)
|
183
|
+
if rule:
|
184
|
+
ft = rule(
|
185
|
+
ft,
|
186
|
+
width,
|
187
|
+
left,
|
188
|
+
token,
|
189
|
+
)
|
190
|
+
|
191
|
+
return ft
|
192
|
+
|
193
|
+
def render_ordered_list(
|
194
|
+
self,
|
195
|
+
tokens: ta.Sequence['Token'],
|
196
|
+
width: int,
|
197
|
+
left: int = 0,
|
198
|
+
) -> ptk.StyleAndTextTuples:
|
199
|
+
"""Render an ordered list by adding indices to the child list items."""
|
200
|
+
|
201
|
+
# Find the list item tokens
|
202
|
+
list_level_tokens = []
|
203
|
+
nest = 0
|
204
|
+
for token in tokens:
|
205
|
+
if nest == 1 and token.tag == 'li':
|
206
|
+
list_level_tokens.append(token)
|
207
|
+
nest += token.nesting
|
208
|
+
|
209
|
+
# Assign them a marking
|
210
|
+
margin_width = len(str(len(list_level_tokens)))
|
211
|
+
for i, token in enumerate(list_level_tokens, start=1):
|
212
|
+
token.attrs['data-margin'] = str(i).rjust(margin_width) + '.'
|
213
|
+
token.attrs['data-list-type'] = 'ol'
|
214
|
+
|
215
|
+
# Now render the tokens as normal
|
216
|
+
return self.render_block(
|
217
|
+
tokens,
|
218
|
+
width=width,
|
219
|
+
left=left,
|
220
|
+
)
|
221
|
+
|
222
|
+
def render_table(
|
223
|
+
self,
|
224
|
+
tokens: ta.Sequence['Token'],
|
225
|
+
width: int,
|
226
|
+
left: int = 0,
|
227
|
+
border: type[Border] = SquareBorder,
|
228
|
+
) -> ptk.StyleAndTextTuples:
|
229
|
+
"""
|
230
|
+
Render a list of parsed markdown tokens representing a table element.
|
231
|
+
|
232
|
+
Args:
|
233
|
+
tokens: The list of parsed tokens to render
|
234
|
+
width: The width at which to render the tokens
|
235
|
+
left: The position on the current line at which to render the output - used to indent subsequent lines when
|
236
|
+
rendering inline blocks like images
|
237
|
+
border: The border style to use to render the table
|
238
|
+
Returns:
|
239
|
+
Formatted text
|
240
|
+
"""
|
241
|
+
|
242
|
+
ft: ptk.StyleAndTextTuples = []
|
243
|
+
|
244
|
+
# Stack the tokens in the shape of the table
|
245
|
+
cell_tokens: list[list[list[Token]]] = []
|
246
|
+
i = 0
|
247
|
+
while i < len(tokens):
|
248
|
+
token = tokens[i]
|
249
|
+
if token.type == 'tr_open':
|
250
|
+
cell_tokens.append([])
|
251
|
+
elif token.type in ('th_open', 'td_open'):
|
252
|
+
for j, token in enumerate(tokens[i:]):
|
253
|
+
if token.type in ('th_close', 'td_close'):
|
254
|
+
cell_tokens[-1].append(list(tokens[i:i + j + 1]))
|
255
|
+
break
|
256
|
+
i += j
|
257
|
+
i += 1
|
258
|
+
|
259
|
+
def _render_token(
|
260
|
+
tokens: ta.Sequence['Token'],
|
261
|
+
width: int | None = None,
|
262
|
+
) -> ptk.StyleAndTextTuples:
|
263
|
+
"""Render a token with correct alignment."""
|
264
|
+
|
265
|
+
side = 'left'
|
266
|
+
|
267
|
+
# Check CSS for text alignment
|
268
|
+
for style_str in str(tokens[0].attrs.get('style', '')).split(';'):
|
269
|
+
if ':' in style_str:
|
270
|
+
key, value = style_str.strip().split(':', 1)
|
271
|
+
if key.strip() == 'text-align':
|
272
|
+
side = value
|
273
|
+
|
274
|
+
# Render with a very long line length if we do not have a width
|
275
|
+
ft = self.render(tokens, width=width or 999999)
|
276
|
+
|
277
|
+
# If we do have a width, wrap and apply the alignment
|
278
|
+
if width:
|
279
|
+
ft = wrap(ft, width)
|
280
|
+
ft = align(_SIDES[side], ft, width)
|
281
|
+
|
282
|
+
return ft
|
283
|
+
|
284
|
+
# Find the naive widths of each cell
|
285
|
+
cell_renders: list[list[ptk.StyleAndTextTuples]] = []
|
286
|
+
cell_widths: list[list[int]] = []
|
287
|
+
for row in cell_tokens:
|
288
|
+
cell_widths.append([])
|
289
|
+
cell_renders.append([])
|
290
|
+
for each_tokens in row:
|
291
|
+
rendered = _render_token(each_tokens)
|
292
|
+
cell_renders[-1].append(rendered)
|
293
|
+
cell_widths[-1].append(ptk.fragment_list_width(rendered))
|
294
|
+
|
295
|
+
# Calculate row and column widths, accounting for broders
|
296
|
+
col_widths = [
|
297
|
+
max([row[i] for row in cell_widths])
|
298
|
+
for i in range(len(cell_widths[0]))
|
299
|
+
]
|
300
|
+
|
301
|
+
# Adjust widths and potentially re-render cells. Reduce biggest cells until we fit in width.
|
302
|
+
while sum(col_widths) + 3 * (len(col_widths) - 1) + 4 > width:
|
303
|
+
idxmax = max(enumerate(col_widths), key=lambda x: x[1])[0]
|
304
|
+
col_widths[idxmax] -= 1
|
305
|
+
|
306
|
+
# Re-render changed cells
|
307
|
+
for i, row_widths in enumerate(cell_widths):
|
308
|
+
for j, new_width in enumerate(col_widths):
|
309
|
+
if row_widths[j] != new_width:
|
310
|
+
cell_renders[i][j] = _render_token(
|
311
|
+
cell_tokens[i][j],
|
312
|
+
width=new_width,
|
313
|
+
)
|
314
|
+
|
315
|
+
# Justify cell contents
|
316
|
+
for i, renders_row in enumerate(cell_renders):
|
317
|
+
for j, cell in enumerate(renders_row):
|
318
|
+
cell_renders[i][j] = align(
|
319
|
+
FormattedTextAlign.LEFT,
|
320
|
+
cell,
|
321
|
+
width=col_widths[j],
|
322
|
+
)
|
323
|
+
|
324
|
+
# Render table
|
325
|
+
style = 'class:md.table.border'
|
326
|
+
|
327
|
+
def _draw_add_border(
|
328
|
+
left: str,
|
329
|
+
split: str,
|
330
|
+
right: str,
|
331
|
+
) -> None:
|
332
|
+
ft.append((style, left + border.HORIZONTAL))
|
333
|
+
|
334
|
+
for col_width in col_widths:
|
335
|
+
ft.append((style, border.HORIZONTAL * col_width))
|
336
|
+
ft.append((style, border.HORIZONTAL + split + border.HORIZONTAL))
|
337
|
+
|
338
|
+
ft.pop()
|
339
|
+
ft.append((style, border.HORIZONTAL + right + '\n'))
|
340
|
+
|
341
|
+
# Draw top border
|
342
|
+
_draw_add_border(
|
343
|
+
border.TOP_LEFT,
|
344
|
+
border.TOP_SPLIT,
|
345
|
+
border.TOP_RIGHT,
|
346
|
+
)
|
347
|
+
|
348
|
+
# Draw each row
|
349
|
+
for i, renders_row in enumerate(cell_renders):
|
350
|
+
for row_lines in itertools.zip_longest(*map(ptk.split_lines, renders_row)):
|
351
|
+
# Draw each line in each row
|
352
|
+
ft.append((style, border.VERTICAL + ' '))
|
353
|
+
|
354
|
+
for j, line in enumerate(row_lines):
|
355
|
+
if line is None:
|
356
|
+
line = [('', ' ' * col_widths[j])]
|
357
|
+
ft += line
|
358
|
+
ft.append((style, ' ' + border.VERTICAL + ' '))
|
359
|
+
|
360
|
+
ft.pop()
|
361
|
+
ft.append((style, ' ' + border.VERTICAL + '\n'))
|
362
|
+
|
363
|
+
# Draw border between rows
|
364
|
+
if i < len(cell_renders) - 1:
|
365
|
+
_draw_add_border(
|
366
|
+
border.LEFT_SPLIT,
|
367
|
+
border.CROSS,
|
368
|
+
border.RIGHT_SPLIT,
|
369
|
+
)
|
370
|
+
|
371
|
+
# Draw bottom border
|
372
|
+
_draw_add_border(
|
373
|
+
border.BOTTOM_LEFT,
|
374
|
+
border.BOTTOM_SPLIT,
|
375
|
+
border.BOTTOM_RIGHT,
|
376
|
+
)
|
377
|
+
|
378
|
+
ft.append(('', '\n'))
|
379
|
+
return ft
|
380
|
+
|
381
|
+
def __pt_formatted_text__(self) -> ptk.StyleAndTextTuples:
|
382
|
+
"""Formatted text magic method."""
|
383
|
+
|
384
|
+
return self.formatted_text
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import typing as ta
|
2
|
+
import warnings
|
3
|
+
|
4
|
+
from omlish import lang
|
5
|
+
|
6
|
+
|
7
|
+
if ta.TYPE_CHECKING:
|
8
|
+
from markdown_it import MarkdownIt
|
9
|
+
|
10
|
+
|
11
|
+
##
|
12
|
+
|
13
|
+
|
14
|
+
@lang.cached_function(lock=True)
|
15
|
+
def markdown_parser() -> ta.Optional['MarkdownIt']:
|
16
|
+
try:
|
17
|
+
from markdown_it import MarkdownIt
|
18
|
+
except ModuleNotFoundError:
|
19
|
+
warnings.warn('The markdown parser requires `markdown-it-py` to be installed')
|
20
|
+
return None
|
21
|
+
|
22
|
+
parser = (
|
23
|
+
MarkdownIt()
|
24
|
+
.enable('linkify')
|
25
|
+
.enable('table')
|
26
|
+
.enable('strikethrough')
|
27
|
+
)
|
28
|
+
|
29
|
+
try:
|
30
|
+
import mdit_py_plugins # noqa F401
|
31
|
+
except ModuleNotFoundError:
|
32
|
+
pass
|
33
|
+
else:
|
34
|
+
from mdit_py_plugins.amsmath import amsmath_plugin # noqa
|
35
|
+
from mdit_py_plugins.dollarmath.index import dollarmath_plugin # noqa
|
36
|
+
from mdit_py_plugins.texmath.index import texmath_plugin # noqa
|
37
|
+
|
38
|
+
parser.use(texmath_plugin)
|
39
|
+
parser.use(dollarmath_plugin)
|
40
|
+
parser.use(amsmath_plugin)
|
41
|
+
|
42
|
+
return parser
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
|
4
|
+
##
|
5
|
+
|
6
|
+
|
7
|
+
MARKDOWN_STYLE: ta.Sequence[tuple[str, str]] = [
|
8
|
+
('md.h1', 'bold underline'),
|
9
|
+
('md.h1.border', 'fg:ansiyellow nounderline'),
|
10
|
+
('md.h2', 'bold'),
|
11
|
+
('md.h2.border', 'fg:grey nobold'),
|
12
|
+
('md.h3', 'bold'),
|
13
|
+
('md.h4', 'bold italic'),
|
14
|
+
('md.h5', 'underline'),
|
15
|
+
('md.h6', 'italic'),
|
16
|
+
('md.code.inline', 'bg:#333'),
|
17
|
+
('md.strong', 'bold'),
|
18
|
+
('md.em', 'italic'),
|
19
|
+
('md.hr', 'fg:ansired'),
|
20
|
+
('md.ul.margin', 'fg:ansiyellow'),
|
21
|
+
('md.ol.margin', 'fg:ansicyan'),
|
22
|
+
('md.blockquote', 'fg:ansipurple'),
|
23
|
+
('md.blockquote.margin', 'fg:grey'),
|
24
|
+
('md.th', 'bold'),
|
25
|
+
('md.a', 'underline fg:ansibrightblue'),
|
26
|
+
('md.s', 'strike'),
|
27
|
+
('md.img', 'bg:cyan fg:black'),
|
28
|
+
('md.img.border', 'fg:cyan bg:default'),
|
29
|
+
]
|