Merge pull request #148 from Adamkadaban/argcomplete-completion
add argcomplete bash/zsh completionmain
commit
dcbb01a39e
|
@ -1,4 +1,4 @@
|
||||||
![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg)
|
![Supported Python versions](https://img.shields.io/badge/python-3.8+-blue.svg)
|
||||||
[![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff)
|
[![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff)
|
||||||
[![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx)
|
[![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx)
|
||||||
[![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck)
|
[![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck)
|
||||||
|
|
26
nxc/cli.py
26
nxc/cli.py
|
@ -1,6 +1,12 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
import argcomplete
|
||||||
import sys
|
import sys
|
||||||
from argparse import RawTextHelpFormatter
|
from argparse import RawTextHelpFormatter
|
||||||
|
from os import listdir
|
||||||
|
from os.path import dirname
|
||||||
|
from os.path import join as path_join
|
||||||
|
import nxc
|
||||||
|
from nxc.paths import NXC_PATH
|
||||||
from nxc.loaders.protocolloader import ProtocolLoader
|
from nxc.loaders.protocolloader import ProtocolLoader
|
||||||
from nxc.helpers.logger import highlight
|
from nxc.helpers.logger import highlight
|
||||||
from nxc.logger import nxc_logger
|
from nxc.logger import nxc_logger
|
||||||
|
@ -41,7 +47,7 @@ def gen_cli_args():
|
||||||
# we do module arg parsing here so we can reference the module_list attribute below
|
# we do module arg parsing here so we can reference the module_list attribute below
|
||||||
module_parser = argparse.ArgumentParser(add_help=False)
|
module_parser = argparse.ArgumentParser(add_help=False)
|
||||||
mgroup = module_parser.add_mutually_exclusive_group()
|
mgroup = module_parser.add_mutually_exclusive_group()
|
||||||
mgroup.add_argument("-M", "--module", action="append", metavar="MODULE", help="module to use")
|
mgroup.add_argument("-M", "--module", choices=get_module_names(), action="append", metavar="MODULE", help="module to use")
|
||||||
module_parser.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
|
module_parser.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
|
||||||
module_parser.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
|
module_parser.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
|
||||||
module_parser.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
|
module_parser.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
|
||||||
|
@ -81,14 +87,28 @@ def gen_cli_args():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}")
|
nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}")
|
||||||
|
|
||||||
|
argcomplete.autocomplete(parser)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.version:
|
if args.version:
|
||||||
print(f"{VERSION} - {CODENAME}")
|
print(f"{VERSION} - {CODENAME}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def get_module_names():
|
||||||
|
"""Get module names without initializing them"""
|
||||||
|
modules = []
|
||||||
|
modules_paths = [
|
||||||
|
path_join(dirname(nxc.__file__), "modules"),
|
||||||
|
path_join(NXC_PATH, "modules"),
|
||||||
|
]
|
||||||
|
|
||||||
|
for path in modules_paths:
|
||||||
|
modules.extend([module[:-3] for module in listdir(path) if module[-3:] == ".py" and module != "example_module.py"])
|
||||||
|
return sorted(modules, key=str.casefold)
|
||||||
|
|
|
@ -24,6 +24,9 @@ class ModuleLoader:
|
||||||
if not hasattr(module, "name"):
|
if not hasattr(module, "name"):
|
||||||
self.logger.fail(f"{module_path} missing the name variable")
|
self.logger.fail(f"{module_path} missing the name variable")
|
||||||
module_error = True
|
module_error = True
|
||||||
|
elif hasattr(module, "name") and module.name != module_path.split("/")[-1][:-3]:
|
||||||
|
self.logger.fail(f"{module_path} filename must match the module name {module.name}")
|
||||||
|
module_error = True
|
||||||
elif not hasattr(module, "description"):
|
elif not hasattr(module, "description"):
|
||||||
self.logger.fail(f"{module_path} missing the description variable")
|
self.logger.fail(f"{module_path} missing the description variable")
|
||||||
module_error = True
|
module_error = True
|
||||||
|
|
|
@ -92,9 +92,6 @@ files = [
|
||||||
{file = "aiosqlite-0.19.0.tar.gz", hash = "sha256:95ee77b91c8d2808bd08a59fbebf66270e9090c3d92ffbf260dc0db0b979577d"},
|
{file = "aiosqlite-0.19.0.tar.gz", hash = "sha256:95ee77b91c8d2808bd08a59fbebf66270e9090c3d92ffbf260dc0db0b979577d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing_extensions = {version = ">=4.0", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["aiounittest (==1.4.1)", "attribution (==1.6.2)", "black (==23.3.0)", "coverage[toml] (==7.2.3)", "flake8 (==5.0.4)", "flake8-bugbear (==23.3.12)", "flit (==3.7.1)", "mypy (==1.2.0)", "ufmt (==2.1.0)", "usort (==1.0.6)"]
|
dev = ["aiounittest (==1.4.1)", "attribution (==1.6.2)", "black (==23.3.0)", "coverage[toml] (==7.2.3)", "flake8 (==5.0.4)", "flake8-bugbear (==23.3.12)", "flit (==3.7.1)", "mypy (==1.2.0)", "ufmt (==2.1.0)", "usort (==1.0.6)"]
|
||||||
docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"]
|
docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"]
|
||||||
|
@ -147,6 +144,20 @@ files = [
|
||||||
{file = "arc4-0.4.0.tar.gz", hash = "sha256:d431b53d11b24d62521dbbd06d755bf9d6d11a03cc7bbbdf37a13a12ee0747b6"},
|
{file = "arc4-0.4.0.tar.gz", hash = "sha256:d431b53d11b24d62521dbbd06d755bf9d6d11a03cc7bbbdf37a13a12ee0747b6"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argcomplete"
|
||||||
|
version = "3.2.1"
|
||||||
|
description = "Bash tab completion for argparse"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "argcomplete-3.2.1-py3-none-any.whl", hash = "sha256:30891d87f3c1abe091f2142613c9d33cac84a5e15404489f033b20399b691fec"},
|
||||||
|
{file = "argcomplete-3.2.1.tar.gz", hash = "sha256:437f67fb9b058da5a090df505ef9be0297c4883993f3f56cb186ff087778cfb4"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["coverage", "mypy", "pexpect", "ruff", "wheel"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asn1crypto"
|
name = "asn1crypto"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
|
@ -220,9 +231,6 @@ files = [
|
||||||
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
|
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
|
||||||
dev = ["attrs[docs,tests]", "pre-commit"]
|
dev = ["attrs[docs,tests]", "pre-commit"]
|
||||||
|
@ -522,7 +530,6 @@ files = [
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
|
@ -649,7 +656,6 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""}
|
|
||||||
mccabe = ">=0.7.0,<0.8.0"
|
mccabe = ">=0.7.0,<0.8.0"
|
||||||
pycodestyle = ">=2.9.0,<2.10.0"
|
pycodestyle = ">=2.9.0,<2.10.0"
|
||||||
pyflakes = ">=2.5.0,<2.6.0"
|
pyflakes = ">=2.5.0,<2.6.0"
|
||||||
|
@ -772,9 +778,6 @@ files = [
|
||||||
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.4"
|
version = "3.4"
|
||||||
|
@ -825,7 +828,6 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
|
|
||||||
zipp = ">=0.5"
|
zipp = ">=0.5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -916,11 +918,9 @@ files = [
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
attrs = ">=17.4.0"
|
attrs = ">=17.4.0"
|
||||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
|
importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
|
||||||
pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""}
|
pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""}
|
||||||
pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2"
|
pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2"
|
||||||
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
|
format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
|
||||||
|
@ -1090,7 +1090,6 @@ files = [
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
mdurl = ">=0.1,<1.0"
|
mdurl = ">=0.1,<1.0"
|
||||||
typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
|
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
|
||||||
|
@ -1521,9 +1520,6 @@ files = [
|
||||||
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
|
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["pre-commit", "tox"]
|
dev = ["pre-commit", "tox"]
|
||||||
testing = ["pytest", "pytest-benchmark"]
|
testing = ["pytest", "pytest-benchmark"]
|
||||||
|
@ -1866,7 +1862,6 @@ files = [
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
|
||||||
iniconfig = "*"
|
iniconfig = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
pluggy = ">=0.12,<2.0"
|
pluggy = ">=0.12,<2.0"
|
||||||
|
@ -2185,7 +2180,6 @@ files = [
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
|
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
|
||||||
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
|
||||||
typing-extensions = ">=4.2.0"
|
typing-extensions = ">=4.2.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -2393,5 +2387,5 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.7.0"
|
python-versions = "^3.8.0"
|
||||||
content-hash = "1ff7892bac10d1469e83c63d338eeca5964a19f39704651cb71a90e045ebb16b"
|
content-hash = "912d573a68ba30b528b05d95f2ec67b2d569e01e32e170ab5551ab2b9422f417"
|
||||||
|
|
|
@ -33,7 +33,7 @@ NetExec = 'nxc.netexec:main'
|
||||||
nxcdb = 'nxc.nxcdb:main'
|
nxcdb = 'nxc.nxcdb:main'
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.7.0"
|
python = "^3.8.0"
|
||||||
requests = ">=2.27.1"
|
requests = ">=2.27.1"
|
||||||
beautifulsoup4 = ">=4.11,<5"
|
beautifulsoup4 = ">=4.11,<5"
|
||||||
lsassy = ">=3.1.8"
|
lsassy = ">=3.1.8"
|
||||||
|
@ -65,6 +65,7 @@ resource = "^0.2.1"
|
||||||
oscrypto = { git = "https://github.com/Pennyw0rth/oscrypto" } # Pypi version currently broken, see: https://github.com/wbond/oscrypto/issues/78 (as of 9/23)
|
oscrypto = { git = "https://github.com/Pennyw0rth/oscrypto" } # Pypi version currently broken, see: https://github.com/wbond/oscrypto/issues/78 (as of 9/23)
|
||||||
pyreadline = "^2.1" # for the build - impacket imports its hidden from the builder so an error occurs
|
pyreadline = "^2.1" # for the build - impacket imports its hidden from the builder so an error occurs
|
||||||
ruff = "=0.0.292"
|
ruff = "=0.0.292"
|
||||||
|
argcomplete = "3.2.1"
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
flake8 = "*"
|
flake8 = "*"
|
||||||
|
@ -123,4 +124,4 @@ target-version = "py37"
|
||||||
[tool.ruff.flake8-quotes]
|
[tool.ruff.flake8-quotes]
|
||||||
docstring-quotes = "double"
|
docstring-quotes = "double"
|
||||||
inline-quotes = "double"
|
inline-quotes = "double"
|
||||||
multiline-quotes = "double"
|
multiline-quotes = "double"
|
||||||
|
|
Loading…
Reference in New Issue