diff --git a/Makefile b/Makefile index 2bae863..74de2bf 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ unlink-systemd-units \ run-clad status-clad \ reload-clad \ + manpages \ # Project directory path - /home//.../command-line-assistant PROJECT_DIR := $(shell pwd) @@ -80,6 +81,7 @@ clean: ## Clean project files .tox \ junit.xml \ coverage.xml + $(MAKE) -C docs clean link-systemd-units: ## Link the systemd units to ~/.config/systemd/user @echo "Linking the systemd units from $(CLAD_SYSTEMD_DEVEL_PATH) to $(SYSTEMD_USER_UNITS)/clad.service" @@ -105,3 +107,8 @@ status-clad: ## Check the status for clad reload-clad: ## Reload clad systemd unit @systemctl --user daemon-reload @systemctl restart --user clad + +man: ## Build manpages + # Build the manpages and change the builddir to match data/release + # Also change the doctrees cache to still use the original build directory. + $(MAKE) BUILDDIR=../data/release SPHINXOPTS=-d=build -C docs man diff --git a/command_line_assistant/initialize.py b/command_line_assistant/initialize.py index 08ad2e9..7bd6b91 100644 --- a/command_line_assistant/initialize.py +++ b/command_line_assistant/initialize.py @@ -1,7 +1,7 @@ """Main module for the cli.""" import sys -from argparse import Namespace +from argparse import ArgumentParser, Namespace from command_line_assistant.commands import history, query, record from command_line_assistant.utils.cli import ( @@ -11,11 +11,11 @@ ) -def initialize() -> int: - """Main function for the cli entrypoint +def register_subcommands() -> ArgumentParser: + """Register all the subcommands for the CLI Returns: - int: Status code of the execution + ArgumentParser: The parser with all the subcommands registered. """ parser, commands_parser = create_argument_parser() @@ -26,6 +26,17 @@ def initialize() -> int: history.register_subcommand(commands_parser) # type: ignore record.register_subcommand(commands_parser) # type: ignore + return parser + + +def initialize() -> int: + """Main function for the cli entrypoint + + Returns: + int: Status code of the execution + """ + parser = register_subcommands() + stdin = read_stdin() args = add_default_command(stdin, sys.argv) diff --git a/command_line_assistant/utils/cli.py b/command_line_assistant/utils/cli.py index c834830..8dbfbbd 100644 --- a/command_line_assistant/utils/cli.py +++ b/command_line_assistant/utils/cli.py @@ -67,6 +67,7 @@ def _subcommand_used(args: list[str]): def create_argument_parser() -> tuple[ArgumentParser, SubParsersAction]: """Create the argument parser for command line assistant.""" parser = ArgumentParser( + prog="c", description="A script with multiple optional arguments and a required positional argument if no optional arguments are provided.", ) parser.add_argument( @@ -79,7 +80,6 @@ def create_argument_parser() -> tuple[ArgumentParser, SubParsersAction]: commands_parser = parser.add_subparsers( dest="command", help="command line assistant helpers" ) - return parser, commands_parser diff --git a/data/release/man/c.1 b/data/release/man/c.1 new file mode 100644 index 0000000..e9f1ad4 --- /dev/null +++ b/data/release/man/c.1 @@ -0,0 +1,137 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "C" "1" "Jan 03, 2025" "0.1.0" "Command Line Assistant" +.SH NAME +c \- Command Line Assistant Client +.sp +A script with multiple optional arguments and a required positional argument if no optional arguments are provided. +.INDENT 0.0 +.INDENT 3.5 +.sp +.EX +c [\-h] [\-\-version] {query,history,record} ... +.EE +.UNINDENT +.UNINDENT +.SH C OPTIONS +.INDENT 0.0 +.IP \(bu 2 +\fI\%\-h\fP, \fI\%\-\-help\fP \- show this help message and exit +.IP \(bu 2 +\fI\%\-\-version\fP \- Show command line assistant version and exit. +.UNINDENT +.SH C QUERY +.sp +Ask a question and get an answer from LLM. +.INDENT 0.0 +.INDENT 3.5 +.sp +.EX +c query [\-h] [query_string] +.EE +.UNINDENT +.UNINDENT +.SS c query positional arguments +.INDENT 0.0 +.IP \(bu 2 +\fI\%query_string\fP \- Query string to be processed. (default: \fBNone\fP) +.UNINDENT +.SS c query options +.INDENT 0.0 +.IP \(bu 2 +\fI\%\-h\fP, \fI\%\-\-help\fP \- show this help message and exit +.UNINDENT +.SH C HISTORY +.sp +Manage conversation history +.INDENT 0.0 +.INDENT 3.5 +.sp +.EX +c history [\-h] [\-\-clear] [\-\-first] [\-\-last] +.EE +.UNINDENT +.UNINDENT +.SS c history options +.INDENT 0.0 +.IP \(bu 2 +\fI\%\-h\fP, \fI\%\-\-help\fP \- show this help message and exit +.IP \(bu 2 +\fI\%\-\-clear\fP \- Clear the history. +.IP \(bu 2 +\fI\%\-\-first\fP \- Get the first conversation from history. +.IP \(bu 2 +\fI\%\-\-last\fP \- Get the last conversation from history. +.UNINDENT +.SH C RECORD +.sp +Start a recording session for script output. +.INDENT 0.0 +.INDENT 3.5 +.sp +.EX +c record [\-h] [\-\-output\-file OUTPUT_FILE] +.EE +.UNINDENT +.UNINDENT +.SS c record options +.INDENT 0.0 +.IP \(bu 2 +\fI\%\-h\fP, \fI\%\-\-help\fP \- show this help message and exit +.IP \(bu 2 +\fI\%\-\-output\-file\fP \fBOUTPUT_FILE\fP \- The place where to store the output file. (default: \fBNone\fP) +.UNINDENT +.INDENT 0.0 +.TP +.B Asking a question: +$ c query \(dqHow do I check disk space?\(dq +.sp +$ c \(dqHow do I check disk space?\(dq +.TP +.B Check all history entries: +$ c history +.TP +.B Check the first entry: +$ c history \-\-first +.TP +.B Check the last entry: +$ c history \-\-last +.TP +.B Clear all the history entries: +$ c history \-\-clear +.UNINDENT +.sp +\fBclad(8)\fP +.SH AUTHOR +RHEL Lightspeed Team +.SH COPYRIGHT +2024, RHEL Lightspeed Team +.\" Generated by docutils manpage writer. +. diff --git a/data/release/man/clad.8 b/data/release/man/clad.8 new file mode 100644 index 0000000..634624a --- /dev/null +++ b/data/release/man/clad.8 @@ -0,0 +1,56 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "CLAD" "8" "Jan 03, 2025" "0.1.0" "Command Line Assistant" +.SH NAME +clad \- Command Line Assistant Daemon +.SH SYNOPSIS +.sp +\fBclad\fP +.SH DESCRIPTION +.sp +The Command Line Assistant daemon (clad) provides the backend service for processing queries through D\-Bus. +.SH FILES +.INDENT 0.0 +.TP +.B \fI/etc/xdg/command\-line\-assistant/config.toml\fP +System configuration file +.TP +.B \fI/var/lib/command\-line\-assistant/history.json\fP +History storage file +.UNINDENT +.SH SEE ALSO +.sp +\fBc(1)\fP +.SH AUTHOR +RHEL Lightspeed Team +.SH COPYRIGHT +2024, RHEL Lightspeed Team +.\" Generated by docutils manpage writer. +. diff --git a/docs/requirements.txt b/docs/requirements.txt index dc23366..8e40c76 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,4 @@ sphinx>=7.4.7 sphinx-autodoc-typehints>=2.3.0 sphinx-rtd-theme>=3.0.2 +sphinx-argparse-cli>=1.17.0 diff --git a/docs/source/conf.py b/docs/source/conf.py index 8488b09..703eeaf 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -9,10 +9,13 @@ import os import sys -project = "command-line-assistant" +project = "Command Line Assistant" copyright = "2024, RHEL Lightspeed Team" author = "RHEL Lightspeed Team" -release = "0.1.0" +release = version = "0.1.0" + +# Add the project root to Python path +sys.path.insert(0, os.path.abspath("../..")) # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -26,6 +29,7 @@ "sphinx.ext.viewcode", # View source code as html "sphinx.ext.todo", # Add todo notes to the docs "sphinx.ext.duration", # Inspect which module is slowing the docs build + "sphinx_argparse_cli", # Auto generate argparse docs for manpage ] intersphinx_mapping = { @@ -49,10 +53,19 @@ default_role = "code" -sys.path.insert(0, os.path.abspath("../..")) +# Other Sphinx settings +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "sphinx_rtd_theme" html_static_path = ["_static"] + +# -- Options for manapge output ---------------------------------------------- +# Man page configuration +man_pages = [ + # (source_start_file, name, description, authors, manual_section) + ("man/command-line-assistant.1", "c", "Command Line Assistant Client", [author], 1), + ("man/clad.8", "clad", "Command Line Assistant Daemon", [author], 8), +] diff --git a/docs/source/index.rst b/docs/source/index.rst index 549c386..c3f9ced 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,6 +23,12 @@ Welcome to Command Line Assistant documentation logger meta +.. toctree:: + :maxdepth: 1 + :caption: Manpage: + + man/index + Indices and tables ================== diff --git a/docs/source/man/clad.8.rst b/docs/source/man/clad.8.rst new file mode 100644 index 0000000..312a056 --- /dev/null +++ b/docs/source/man/clad.8.rst @@ -0,0 +1,28 @@ +.. _clad.8: + +Command Line Assistant Daemon +============================= + +Synopsis +-------- + +**clad** + +Description +----------- + +The Command Line Assistant daemon (clad) provides the backend service for processing queries through D-Bus. + +Files +----- + +*/etc/xdg/command-line-assistant/config.toml* + System configuration file + +*/var/lib/command-line-assistant/history.json* + History storage file + +See Also +-------- + +**c(1)** diff --git a/docs/source/man/command-line-assistant.1.rst b/docs/source/man/command-line-assistant.1.rst new file mode 100644 index 0000000..5dc6c63 --- /dev/null +++ b/docs/source/man/command-line-assistant.1.rst @@ -0,0 +1,30 @@ +.. sphinx_argparse_cli:: + :module: command_line_assistant.initialize + :func: register_subcommands + :prog: c + :title: Command Line Assistant + +Examples +-------- + +Asking a question: + $ c query "How do I check disk space?" + + $ c "How do I check disk space?" + +Check all history entries: + $ c history + +Check the first entry: + $ c history --first + +Check the last entry: + $ c history --last + +Clear all the history entries: + $ c history --clear + +See Also +-------- + +**clad(8)** diff --git a/docs/source/man/index.rst b/docs/source/man/index.rst new file mode 100644 index 0000000..bf5a297 --- /dev/null +++ b/docs/source/man/index.rst @@ -0,0 +1,10 @@ +.. _man_pages: + +Man Pages +========= + +.. toctree:: + :maxdepth: 1 + + command-line-assistant.1 + clad.8 diff --git a/packaging/command-line-assistant.spec b/packaging/command-line-assistant.spec index 5d680ba..e0f42d7 100644 --- a/packaging/command-line-assistant.spec +++ b/packaging/command-line-assistant.spec @@ -41,9 +41,12 @@ A simple wrapper to interact with RAG %install %py3_install_wheel %{python_package_src}-%{version}-py3-none-any.whl -# Create sbin directory in buildroot +# Create needed directories in buildroot %{__install} -d %{buildroot}/%{_sbindir} %{__install} -d %{buildroot}/%{_sysconfdir}/xdg/%{python_package_src} +%{__install} -d %{buildroot}/%{_sharedstatedir}/%{name} +%{__install} -d %{buildroot}/%{_mandir}/man1 +%{__install} -d %{buildroot}/%{_mandir}/man8 # Move the daemon to /usr/sbin instead of /usr/bin %{__install} -m 0755 %{buildroot}/%{_bindir}/%{daemon_binary_name} %{buildroot}/%{_sbindir}/%{daemon_binary_name} @@ -61,11 +64,12 @@ A simple wrapper to interact with RAG %{__install} -D -m 0644 data/release/xdg/config.toml %{buildroot}/%{_sysconfdir}/xdg/%{python_package_src}/config.toml # History file -## Create the folder under /var/lib/command-line-assistatnt -%{__install} -d %{buildroot}/%{_sharedstatedir}/%{name} -## Place the history file there %{__install} -D -m 0644 data/release/xdg/history.json %{buildroot}/%{_sharedstatedir}/%{name}/history.json +# Manpages +%{__install} -D -m 0644 data/release/man/%{binary_name}.1 %{buildroot}/%{_mandir}/man1/%{binary_name}.1 +%{__install} -D -m 0644 data/release/man/%{daemon_binary_name}.8 %{buildroot}/%{_mandir}/man8/%{daemon_binary_name}.8 + %post %systemd_post %{daemon_binary_name}.service @@ -75,9 +79,13 @@ A simple wrapper to interact with RAG %postun %systemd_postun_with_restart %{daemon_binary_name}.service +%doc +README.md + +%license +LICENSE + %files -%doc README.md -%license LICENSE %{python3_sitelib}/%{python_package_src}/ %{python3_sitelib}/%{python_package_src}-%{version}.dist-info/ @@ -99,4 +107,8 @@ A simple wrapper to interact with RAG # History file %{_sharedstatedir}/%{name}/history.json +# Manpages +%{_mandir}/man1/%{binary_name}.1.gz +%{_mandir}/man8/%{daemon_binary_name}.8.gz + %changelog diff --git a/pdm.lock b/pdm.lock index bfcade7..0cd114e 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:025e14d603ed8cb8e6671ec783e7f98a6c76c4e8960f46e04ad39cbb63df0296" +content_hash = "sha256:d314b2d22c5ff42fb0d68d7cac161bc8514119924c90fde6b0648a819278db6a" [[metadata.targets]] requires_python = ">=3.9" @@ -841,6 +841,34 @@ files = [ {file = "sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe"}, ] +[[package]] +name = "sphinx-argparse" +version = "0.4.0" +requires_python = ">=3.7" +summary = "A sphinx extension that automatically documents argparse commands and options" +groups = ["dev"] +dependencies = [ + "sphinx>=1.2.0", +] +files = [ + {file = "sphinx_argparse-0.4.0-py3-none-any.whl", hash = "sha256:73bee01f7276fae2bf621ccfe4d167af7306e7288e3482005405d9f826f9b037"}, + {file = "sphinx_argparse-0.4.0.tar.gz", hash = "sha256:e0f34184eb56f12face774fbc87b880abdb9017a0998d1ec559b267e9697e449"}, +] + +[[package]] +name = "sphinx-argparse-cli" +version = "1.17.0" +requires_python = ">=3.9" +summary = "render CLI arguments (sub-commands friendly) defined by argparse module" +groups = ["dev"] +dependencies = [ + "sphinx>=7.3.7", +] +files = [ + {file = "sphinx_argparse_cli-1.17.0-py3-none-any.whl", hash = "sha256:0d5ba16d012b11b33bb0bc508bb4176ee62b5cafaacfbac9070a8e86e308380c"}, + {file = "sphinx_argparse_cli-1.17.0.tar.gz", hash = "sha256:f32a1d359756ba113d1e211d22934a3c7c43f862acd204f72803f9b2ac49da4f"}, +] + [[package]] name = "sphinx-autodoc-typehints" version = "2.3.0" diff --git a/pyproject.toml b/pyproject.toml index bdd1bc5..7b8c2d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dev = [ "sphinx>=7.4.7", "sphinx-autodoc-typehints>=2.3.0", "sphinx-rtd-theme>=3.0.2", + "sphinx-argparse-cli>=1.17.0", ] # ----- Tooling specifics