omdev 0.0.0.dev463__tar.gz → 0.0.0.dev464__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.dev463/omdev.egg-info → omdev-0.0.0.dev464}/PKG-INFO +2 -2
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/__init__.py +1 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/__init__.py +16 -0
- omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/LICENSE +21 -0
- omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/__init__.py +33 -0
- omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/matching.py +226 -0
- omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/paths.py +202 -0
- omdev-0.0.0.dev464/omdev/tui/textual/autocomplete/widget.py +612 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/SOURCES.txt +6 -1
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/pyproject.toml +2 -2
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/LICENSE +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/README.md +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/.omlish-manifests.json +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/cli/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/cli/main.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/gen.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/imports.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/manifests.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/resources.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/srcfiles.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/strip.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/types.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/gen/typing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/amalg/sources.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/aps.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/ax.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/cf.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/darwin/cg.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/linux/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/capi/linux/x11.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cdeps.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cdeps.toml +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cc/srclangs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/ci.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/compose.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/consts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/buildcaching.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cacheserved/manifests.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/cmds.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/dataserver.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/imagepulling.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/packing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/repositories.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/docker/utils.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/clients.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/api.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v1/client.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/api.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/azure.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/api/v2/client.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/bootstrap.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/cache.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/env.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/github/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/requirements.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/shell.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/ci/utils.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/_cmdlog.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/cmdlog/cmdlog.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataclasses/codegen.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/handlers.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/http.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/routes.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/server.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/dataserver/targets.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/magic.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/shallow.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/paths.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/secrets.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/home/shadow.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/ides.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/intellij/open.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/default.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/install.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/provider.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/pyenv/pyenv.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/provider.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/base.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/formats.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/messages.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/messages/parsing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/formats.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/numerics.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/numerics/types.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/LICENSE +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/consts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/errors.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/message.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/nuh.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/parsing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/rendering.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/tags.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/irc/protocol/utils.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/_dumping.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/building.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/dumping.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/incparse.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/markdown/tokens.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/mypy/report.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/building.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/compression.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/data.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/datarefs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/dataserver.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/loading.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/media.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/packing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/repositories.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/pack/unpacking.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/repositories.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/oci/tars.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/revisions.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/packaging/wheelfile.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/blanklines.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/caches.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/imports.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/precheck/unicode.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/attrdocs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/bracepy.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/classdot.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/LICENSE +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/attrdoc.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/common.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/epydoc.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/google.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/numpydoc.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/parser.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/docstrings/rest.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/findimports.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/execstat.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/srcheaders.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/importscan.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/py/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/docker-dev.sh +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/resources/python.sh +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/ci.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/inject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/logs.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/lib/marshal.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tagstrings.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/all.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/tokenizert.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tokens/utils.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/diff.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/cloning.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/consts.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/git/messages.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/jsonview.css +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/jsonview/resources/jsonview.js +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/linehisto.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/mkenv.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/shadow.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/shell.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/app.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/client.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/commands.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/irc/main.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/__init__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/__main__.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/apps/markdown/cli.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/console2.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/rich/markdown2.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/app2.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev/tui/textual/drivers2.py +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev463 → omdev-0.0.0.dev464}/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.dev464
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: omlish==0.0.0.
|
|
17
|
+
Requires-Dist: omlish==0.0.0.dev464
|
|
18
18
|
Provides-Extra: all
|
|
19
19
|
Requires-Dist: black~=25.9; extra == "all"
|
|
20
20
|
Requires-Dist: pycparser~=2.23; extra == "all"
|
|
@@ -9,6 +9,7 @@ with _lang.auto_proxy_init(globals()):
|
|
|
9
9
|
from rich import console # noqa
|
|
10
10
|
from rich import live # noqa
|
|
11
11
|
from rich import markdown # noqa
|
|
12
|
+
from rich import repr # noqa
|
|
12
13
|
from rich import text # noqa
|
|
13
14
|
from rich.console import Console # noqa
|
|
14
15
|
from rich.live import Live # noqa
|
|
@@ -8,13 +8,16 @@ with _lang.auto_proxy_init(globals()):
|
|
|
8
8
|
|
|
9
9
|
from textual import app # noqa
|
|
10
10
|
from textual import binding # noqa
|
|
11
|
+
from textual import constants # noqa
|
|
11
12
|
from textual import containers # noqa
|
|
12
13
|
from textual import content # noqa
|
|
13
14
|
from textual import driver # noqa
|
|
14
15
|
from textual import events # noqa
|
|
16
|
+
from textual import geometry # noqa
|
|
15
17
|
from textual import markup # noqa
|
|
16
18
|
from textual import message # noqa
|
|
17
19
|
from textual import messages # noqa
|
|
20
|
+
from textual import on # noqa
|
|
18
21
|
from textual import pad # noqa
|
|
19
22
|
from textual import reactive # noqa
|
|
20
23
|
from textual import screen # noqa
|
|
@@ -116,6 +119,16 @@ with _lang.auto_proxy_init(globals()):
|
|
|
116
119
|
from textual.events import Show # noqa
|
|
117
120
|
from textual.events import Timer as TimerEvent # noqa
|
|
118
121
|
from textual.events import Unmount # noqa
|
|
122
|
+
from textual.geometry import NULL_OFFSET # noqa
|
|
123
|
+
from textual.geometry import NULL_REGION # noqa
|
|
124
|
+
from textual.geometry import NULL_SIZE # noqa
|
|
125
|
+
from textual.geometry import NULL_SPACING # noqa
|
|
126
|
+
from textual.geometry import Offset # noqa
|
|
127
|
+
from textual.geometry import Region # noqa
|
|
128
|
+
from textual.geometry import Size # noqa
|
|
129
|
+
from textual.geometry import Spacing # noqa
|
|
130
|
+
from textual.geometry import SpacingDimensions # noqa
|
|
131
|
+
from textual.geometry import clamp # noqa
|
|
119
132
|
from textual.markup import MarkupError # noqa
|
|
120
133
|
from textual.markup import MarkupTokenizer # noqa
|
|
121
134
|
from textual.markup import StyleTokenizer # noqa
|
|
@@ -197,6 +210,9 @@ with _lang.auto_proxy_init(globals()):
|
|
|
197
210
|
from textual.widgets import Tooltip # noqa
|
|
198
211
|
from textual.widgets import Tree # noqa
|
|
199
212
|
from textual.widgets import Welcome # noqa
|
|
213
|
+
from textual.widgets.option_list import OptionDoesNotExist # noqa
|
|
214
|
+
from textual.widgets.option_list import Option # noqa
|
|
215
|
+
from textual.widgets.option_list import DuplicateID # noqa
|
|
200
216
|
|
|
201
217
|
##
|
|
202
218
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Darren Burns
|
|
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.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2023 Darren Burns
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
6
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
8
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
11
|
+
# Software.
|
|
12
|
+
#
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
14
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
15
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
16
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
17
|
+
#
|
|
18
|
+
# https://github.com/darrenburns/textual-autocomplete/tree/0344cd3eb3383cbbd80e01b035ed808ce53cef4d
|
|
19
|
+
from .matching import ( # noqa
|
|
20
|
+
FuzzySearch,
|
|
21
|
+
FuzzyMatcher,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from .paths import ( # noqa
|
|
25
|
+
PathAutoComplete,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
from .widget import ( # noqa
|
|
29
|
+
AutoCompleteItem,
|
|
30
|
+
AutoCompleteItemHit,
|
|
31
|
+
AutoCompleteList,
|
|
32
|
+
AutoComplete,
|
|
33
|
+
)
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import operator
|
|
3
|
+
import re
|
|
4
|
+
import typing as ta
|
|
5
|
+
|
|
6
|
+
import rich.repr
|
|
7
|
+
from textual.cache import LRUCache
|
|
8
|
+
from textual.content import Content
|
|
9
|
+
from textual.style import Style
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FuzzySearch:
|
|
16
|
+
"""
|
|
17
|
+
Performs a fuzzy search.
|
|
18
|
+
|
|
19
|
+
Unlike a regex solution, this will finds all possible matches.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
case_sensitive: bool = False,
|
|
25
|
+
*,
|
|
26
|
+
cache_size: int = 1024 * 4,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""
|
|
29
|
+
Initialize fuzzy search.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
case_sensitive: Is the match case sensitive?
|
|
33
|
+
cache_size: Number of queries to cache.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
self.case_sensitive = case_sensitive
|
|
37
|
+
self.cache: LRUCache[tuple[str, str], tuple[float, ta.Sequence[int]]] = LRUCache(cache_size)
|
|
38
|
+
|
|
39
|
+
def match(self, query: str, candidate: str) -> tuple[float, ta.Sequence[int]]:
|
|
40
|
+
"""
|
|
41
|
+
Match against a query.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
query: The fuzzy query.
|
|
45
|
+
candidate: A candidate to check,.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A pair of (score, tuple of offsets). `(0, ())` for no result.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
cache_key = (query, candidate)
|
|
52
|
+
if cache_key in self.cache:
|
|
53
|
+
return self.cache[cache_key]
|
|
54
|
+
default: tuple[float, ta.Sequence[int]] = (0.0, [])
|
|
55
|
+
result = max(self._match(query, candidate), key=operator.itemgetter(0), default=default)
|
|
56
|
+
self.cache[cache_key] = result
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
@functools.lru_cache(maxsize=1024)
|
|
61
|
+
def get_first_letters(cls, candidate: str) -> frozenset[int]:
|
|
62
|
+
return frozenset({match.start() for match in re.finditer(r'\w+', candidate)})
|
|
63
|
+
|
|
64
|
+
def score(self, candidate: str, positions: ta.Sequence[int]) -> float:
|
|
65
|
+
"""
|
|
66
|
+
Score a search.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
search: Search object.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Score.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
first_letters = self.get_first_letters(candidate)
|
|
76
|
+
# This is a heuristic, and can be tweaked for better results.
|
|
77
|
+
# Boost first letter matches.
|
|
78
|
+
offset_count = len(positions)
|
|
79
|
+
score: float = offset_count + len(first_letters.intersection(positions))
|
|
80
|
+
|
|
81
|
+
groups = 1
|
|
82
|
+
last_offset, *offsets = positions
|
|
83
|
+
for offset in offsets:
|
|
84
|
+
if offset != last_offset + 1:
|
|
85
|
+
groups += 1
|
|
86
|
+
last_offset = offset
|
|
87
|
+
|
|
88
|
+
# Boost to favor less groups
|
|
89
|
+
normalized_groups = (offset_count - (groups - 1)) / offset_count
|
|
90
|
+
score *= 1 + (normalized_groups * normalized_groups)
|
|
91
|
+
return score
|
|
92
|
+
|
|
93
|
+
def _match(self, query: str, candidate: str) -> ta.Iterable[tuple[float, ta.Sequence[int]]]:
|
|
94
|
+
letter_positions: list[list[int]] = []
|
|
95
|
+
position = 0
|
|
96
|
+
|
|
97
|
+
if not self.case_sensitive:
|
|
98
|
+
candidate = candidate.lower()
|
|
99
|
+
query = query.lower()
|
|
100
|
+
score = self.score
|
|
101
|
+
if query in candidate:
|
|
102
|
+
# Quick exit when the query exists as a substring
|
|
103
|
+
query_location = candidate.rfind(query)
|
|
104
|
+
offsets = list(range(query_location, query_location + len(query)))
|
|
105
|
+
yield (
|
|
106
|
+
score(candidate, offsets) * (2.0 if candidate == query else 1.5),
|
|
107
|
+
offsets,
|
|
108
|
+
)
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
for offset, letter in enumerate(query):
|
|
112
|
+
last_index = len(candidate) - offset
|
|
113
|
+
positions: list[int] = []
|
|
114
|
+
letter_positions.append(positions)
|
|
115
|
+
index = position
|
|
116
|
+
while (location := candidate.find(letter, index)) != -1:
|
|
117
|
+
positions.append(location)
|
|
118
|
+
index = location + 1
|
|
119
|
+
if index >= last_index:
|
|
120
|
+
break
|
|
121
|
+
if not positions:
|
|
122
|
+
yield (0.0, ())
|
|
123
|
+
return
|
|
124
|
+
position = positions[0] + 1
|
|
125
|
+
|
|
126
|
+
possible_offsets: list[list[int]] = []
|
|
127
|
+
query_length = len(query)
|
|
128
|
+
|
|
129
|
+
def get_offsets(offsets: list[int], positions_index: int) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Recursively match offsets.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
offsets: A list of offsets.
|
|
135
|
+
positions_index: Index of query letter.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
for offset in letter_positions[positions_index]:
|
|
139
|
+
if not offsets or offset > offsets[-1]:
|
|
140
|
+
new_offsets = [*offsets, offset]
|
|
141
|
+
if len(new_offsets) == query_length:
|
|
142
|
+
possible_offsets.append(new_offsets)
|
|
143
|
+
else:
|
|
144
|
+
get_offsets(new_offsets, positions_index + 1)
|
|
145
|
+
|
|
146
|
+
get_offsets([], 0)
|
|
147
|
+
|
|
148
|
+
for offsets in possible_offsets:
|
|
149
|
+
yield score(candidate, offsets), offsets
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@rich.repr.auto
|
|
153
|
+
class FuzzyMatcher:
|
|
154
|
+
"""A fuzzy matcher."""
|
|
155
|
+
|
|
156
|
+
def __init__(
|
|
157
|
+
self,
|
|
158
|
+
query: str,
|
|
159
|
+
*,
|
|
160
|
+
match_style: Style | None = None,
|
|
161
|
+
case_sensitive: bool = False,
|
|
162
|
+
) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Initialize the fuzzy matching object.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
query: A query as typed in by the user.
|
|
168
|
+
match_style: The style to use to highlight matched portions of a string.
|
|
169
|
+
case_sensitive: Should matching be case sensitive?
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
self._query = query
|
|
173
|
+
self._match_style = Style(reverse=True) if match_style is None else match_style
|
|
174
|
+
self._case_sensitive = case_sensitive
|
|
175
|
+
self.fuzzy_search = FuzzySearch()
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def query(self) -> str:
|
|
179
|
+
"""The query string to look for."""
|
|
180
|
+
|
|
181
|
+
return self._query
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def match_style(self) -> Style:
|
|
185
|
+
"""The style that will be used to highlight hits in the matched text."""
|
|
186
|
+
|
|
187
|
+
return self._match_style
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def case_sensitive(self) -> bool:
|
|
191
|
+
"""Is this matcher case sensitive?"""
|
|
192
|
+
|
|
193
|
+
return self._case_sensitive
|
|
194
|
+
|
|
195
|
+
def match(self, candidate: str) -> float:
|
|
196
|
+
"""
|
|
197
|
+
Match the candidate against the query.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
candidate: Candidate string to match against the query.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Strength of the match from 0 to 1.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
return self.fuzzy_search.match(self.query, candidate)[0]
|
|
207
|
+
|
|
208
|
+
def highlight(self, candidate: str) -> Content:
|
|
209
|
+
"""
|
|
210
|
+
Highlight the candidate with the fuzzy match.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
candidate: The candidate string to match against the query.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
A [`Text`][rich.text.Text] object with highlighted matches.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
content = Content.from_markup(candidate)
|
|
220
|
+
score, offsets = self.fuzzy_search.match(self.query, candidate)
|
|
221
|
+
if not score:
|
|
222
|
+
return content
|
|
223
|
+
for offset in offsets:
|
|
224
|
+
if not candidate[offset].isspace():
|
|
225
|
+
content = content.stylize(self._match_style, offset, offset + 1)
|
|
226
|
+
return content
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pathlib
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
from textual.cache import LRUCache
|
|
6
|
+
from textual.content import Content
|
|
7
|
+
from textual.widgets import Input
|
|
8
|
+
|
|
9
|
+
from .widget import AutoComplete
|
|
10
|
+
from .widget import AutoCompleteItem
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PathAutoCompleteItem(AutoCompleteItem):
|
|
17
|
+
def __init__(self, completion: str, path: pathlib.Path) -> None:
|
|
18
|
+
super().__init__(completion)
|
|
19
|
+
|
|
20
|
+
self.path = path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def default_path_input_sort_key(item: PathAutoCompleteItem) -> tuple[bool, bool, str]:
|
|
24
|
+
"""
|
|
25
|
+
Sort key function for results within the dropdown.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
item: The PathAutoCompleteItem to get a sort key for.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
A tuple of (is_dotfile, is_file, lowercase_name) for sorting.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
name = item.path.name
|
|
35
|
+
is_dotfile = name.startswith('.')
|
|
36
|
+
return (not item.path.is_dir(), not is_dotfile, name.lower())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class PathAutoComplete(AutoComplete):
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
target: Input | str,
|
|
43
|
+
path: str | pathlib.Path = '.',
|
|
44
|
+
*,
|
|
45
|
+
show_dotfiles: bool = True,
|
|
46
|
+
sort_key: ta.Callable[[PathAutoCompleteItem], ta.Any] = default_path_input_sort_key,
|
|
47
|
+
folder_prefix: Content = Content('📂'),
|
|
48
|
+
file_prefix: Content = Content('📄'),
|
|
49
|
+
prevent_default_enter: bool = True,
|
|
50
|
+
prevent_default_tab: bool = True,
|
|
51
|
+
cache_size: int = 100,
|
|
52
|
+
name: str | None = None,
|
|
53
|
+
id: str | None = None, # noqa
|
|
54
|
+
classes: str | None = None,
|
|
55
|
+
disabled: bool = False,
|
|
56
|
+
) -> None:
|
|
57
|
+
"""
|
|
58
|
+
An autocomplete widget for filesystem paths.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
target: The target input widget to autocomplete.
|
|
62
|
+
path: The base path to autocomplete from.
|
|
63
|
+
show_dotfiles: Whether to show dotfiles (files/dirs starting with ".").
|
|
64
|
+
sort_key: Function to sort the dropdown items.
|
|
65
|
+
folder_prefix: The prefix for folder items (e.g. 📂).
|
|
66
|
+
file_prefix: The prefix for file items (e.g. 📄).
|
|
67
|
+
prevent_default_enter: Whether to prevent the default enter behavior.
|
|
68
|
+
prevent_default_tab: Whether to prevent the default tab behavior.
|
|
69
|
+
cache_size: The number of directories to cache.
|
|
70
|
+
name: The name of the widget.
|
|
71
|
+
id: The DOM node id of the widget.
|
|
72
|
+
classes: The CSS classes of the widget.
|
|
73
|
+
disabled: Whether the widget is disabled.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
super().__init__(
|
|
77
|
+
target,
|
|
78
|
+
None,
|
|
79
|
+
prevent_default_enter=prevent_default_enter,
|
|
80
|
+
prevent_default_tab=prevent_default_tab,
|
|
81
|
+
name=name,
|
|
82
|
+
id=id,
|
|
83
|
+
classes=classes,
|
|
84
|
+
disabled=disabled,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.path = pathlib.Path(path) if isinstance(path, str) else path
|
|
88
|
+
self.show_dotfiles = show_dotfiles
|
|
89
|
+
self.sort_key = sort_key
|
|
90
|
+
self.folder_prefix = folder_prefix
|
|
91
|
+
self.file_prefix = file_prefix
|
|
92
|
+
self._directory_cache: LRUCache[str, list[os.DirEntry[str]]] = LRUCache(cache_size)
|
|
93
|
+
|
|
94
|
+
def get_candidates(self, target_state: AutoComplete.TargetState) -> list[AutoCompleteItem]:
|
|
95
|
+
"""
|
|
96
|
+
Get the candidates for the current path segment.
|
|
97
|
+
|
|
98
|
+
This is called each time the input changes or the cursor position changes/
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
current_input = target_state.text[: target_state.cursor_position]
|
|
102
|
+
|
|
103
|
+
if '/' in current_input:
|
|
104
|
+
last_slash_index = current_input.rindex('/')
|
|
105
|
+
path_segment = current_input[:last_slash_index] or '/'
|
|
106
|
+
directory = self.path / path_segment if path_segment != '/' else self.path
|
|
107
|
+
else:
|
|
108
|
+
directory = self.path
|
|
109
|
+
|
|
110
|
+
# Use the directory path as the cache key
|
|
111
|
+
cache_key = str(directory)
|
|
112
|
+
cached_entries = self._directory_cache.get(cache_key)
|
|
113
|
+
|
|
114
|
+
if cached_entries is not None:
|
|
115
|
+
entries = cached_entries
|
|
116
|
+
else:
|
|
117
|
+
try:
|
|
118
|
+
entries = list(os.scandir(directory))
|
|
119
|
+
self._directory_cache[cache_key] = entries
|
|
120
|
+
except OSError:
|
|
121
|
+
return []
|
|
122
|
+
|
|
123
|
+
results: list[PathAutoCompleteItem] = []
|
|
124
|
+
for entry in entries:
|
|
125
|
+
# Only include the entry name, not the full path
|
|
126
|
+
completion = entry.name
|
|
127
|
+
if not self.show_dotfiles and completion.startswith('.'):
|
|
128
|
+
continue
|
|
129
|
+
if entry.is_dir():
|
|
130
|
+
completion += '/'
|
|
131
|
+
results.append(PathAutoCompleteItem(completion, path=pathlib.Path(entry.path)))
|
|
132
|
+
|
|
133
|
+
results.sort(key=self.sort_key)
|
|
134
|
+
folder_prefix = self.folder_prefix
|
|
135
|
+
file_prefix = self.file_prefix
|
|
136
|
+
return [
|
|
137
|
+
AutoCompleteItem(
|
|
138
|
+
item.main,
|
|
139
|
+
prefix=folder_prefix if item.path.is_dir() else file_prefix,
|
|
140
|
+
)
|
|
141
|
+
for item in results
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
def get_search_string(self, target_state: AutoComplete.TargetState) -> str:
|
|
145
|
+
"""Return only the current path segment for searching in the dropdown."""
|
|
146
|
+
|
|
147
|
+
current_input = target_state.text[: target_state.cursor_position]
|
|
148
|
+
|
|
149
|
+
if '/' in current_input:
|
|
150
|
+
last_slash_index = current_input.rindex('/')
|
|
151
|
+
search_string = current_input[last_slash_index + 1:]
|
|
152
|
+
return search_string
|
|
153
|
+
else:
|
|
154
|
+
return current_input
|
|
155
|
+
|
|
156
|
+
def apply_completion(self, value: str, state: AutoComplete.TargetState) -> None:
|
|
157
|
+
"""Apply the completion by replacing only the current path segment."""
|
|
158
|
+
|
|
159
|
+
target = self.target
|
|
160
|
+
current_input = state.text
|
|
161
|
+
cursor_position = state.cursor_position
|
|
162
|
+
|
|
163
|
+
# There's a slash before the cursor, so we only want to replace the text after the last slash with the selected
|
|
164
|
+
# value
|
|
165
|
+
try:
|
|
166
|
+
replace_start_index = current_input.rindex('/', 0, cursor_position)
|
|
167
|
+
except ValueError:
|
|
168
|
+
# No slashes, so we do a full replacement
|
|
169
|
+
new_value = value
|
|
170
|
+
new_cursor_position = len(value)
|
|
171
|
+
else:
|
|
172
|
+
# Keep everything before and including the slash before the cursor.
|
|
173
|
+
path_prefix = current_input[: replace_start_index + 1]
|
|
174
|
+
new_value = path_prefix + value
|
|
175
|
+
new_cursor_position = len(path_prefix) + len(value)
|
|
176
|
+
|
|
177
|
+
with self.prevent(Input.Changed):
|
|
178
|
+
target.value = new_value
|
|
179
|
+
target.cursor_position = new_cursor_position
|
|
180
|
+
|
|
181
|
+
def post_completion(self) -> None:
|
|
182
|
+
if not self.target.value.endswith('/'):
|
|
183
|
+
self.action_hide()
|
|
184
|
+
|
|
185
|
+
def should_show_dropdown(self, search_string: str) -> bool:
|
|
186
|
+
return (
|
|
187
|
+
super().should_show_dropdown(search_string) or
|
|
188
|
+
(
|
|
189
|
+
(search_string == '' and self.target.value != '') and
|
|
190
|
+
self.option_list.option_count > 1
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def clear_directory_cache(self) -> None:
|
|
195
|
+
"""
|
|
196
|
+
Clear the directory cache. If you know that the contents of the directory have changed, you can call this method
|
|
197
|
+
to invalidate the cache.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
self._directory_cache.clear()
|
|
201
|
+
target_state = self._get_target_state()
|
|
202
|
+
self._rebuild_options(target_state, self.get_search_string(target_state))
|