Repository: aws/aws-cli

Issue:
Add support for mandoc
### Describe the feature

Linux distros and BSD systems that use `mandoc` instead of `groff` should be supported to display 'help' documentation without the need for installing additional sofware. 

### Use Case

'Help' docs should be able to be displayed on Linux distros and BSD systems that don't use `groff`.

### Proposed Solution

PR #2635 adds support for this feature request.

### Other Information

_No response_

### Acknowledgements

- [ ] I may be able to implement this feature request
- [ ] This feature might incur a breaking change

### CLI version used

2.6.2

### Environment details (OS name and version, etc.)

aws-cli/2.6.2 Python/3.9.11 Darwin/20.6.0 exe/x86_64 prompt/off

Discussion:
codecov-commenter: # [Codecov](https://codecov.io/gh/aws/aws-cli/pull/7413?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws) Report
> Merging [#7413](https://codecov.io/gh/aws/aws-cli/pull/7413?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws) (21523d3) into [develop](https://codecov.io/gh/aws/aws-cli/commit/277e232130cac7167d8c411cf3a8bedbf5ff0713?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws) (277e232) will **decrease** coverage by `0.00%`.
> The diff coverage is `0.00%`.

```diff
@@            Coverage Diff             @@
##           develop   #7413      +/-   ##
==========================================
- Coverage     0.08%   0.08%   -0.01%     
==========================================
  Files          205     205              
  Lines        16455   16457       +2     
==========================================
  Hits            14      14              
- Misses       16441   16443       +2     
```


| [Impacted Files](https://codecov.io/gh/aws/aws-cli/pull/7413?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws) | Coverage Δ | |
|---|---|---|
| [awscli/help.py](https://codecov.io/gh/aws/aws-cli/pull/7413/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws#diff-YXdzY2xpL2hlbHAucHk=) | `0.00% <0.00%> (ø)` | |
| [awscli/testutils.py](https://codecov.io/gh/aws/aws-cli/pull/7413/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws#diff-YXdzY2xpL3Rlc3R1dGlscy5weQ==) | `0.00% <ø> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aws)


Patch:
diff --git a/.changes/next-release/enhancement-docs-15168.json b/.changes/next-release/enhancement-docs-15168.json
new file mode 100644
index 000000000..48545bf52
--- /dev/null
+++ b/.changes/next-release/enhancement-docs-15168.json
@@ -0,0 +1,5 @@
+{
+  "type": "enhancement",
+  "category": "docs",
+  "description": "Fixes `#6918 <https://github.com/aws/aws-cli/issues/6918>`__ and `#7400 <https://github.com/aws/aws-cli/issues/7400>`__. The CLI falls back on mandoc if groff isn't available."
+}
diff --git a/awscli/help.py b/awscli/help.py
index 0ab6328fb..f2ef22b99 100644
--- a/awscli/help.py
+++ b/awscli/help.py
@@ -106,13 +106,16 @@ class PosixHelpRenderer(PagingHelpRenderer):
 
     def _convert_doc_content(self, contents):
         man_contents = publish_string(contents, writer=manpage.Writer())
-        if not self._exists_on_path('groff'):
-            raise ExecutableNotFoundError('groff')
-        cmdline = ['groff', '-m', 'man', '-T', 'ascii']
+        if self._exists_on_path('groff'):
+            cmdline = ['groff', '-m', 'man', '-T', 'ascii']
+        elif self._exists_on_path('mandoc'):
+            cmdline = ['mandoc', '-T', 'ascii']
+        else:
+            raise ExecutableNotFoundError('groff or mandoc')
         LOG.debug("Running command: %s", cmdline)
         p3 = self._popen(cmdline, stdin=PIPE, stdout=PIPE, stderr=PIPE)
-        groff_output = p3.communicate(input=man_contents)[0]
-        return groff_output
+        output = p3.communicate(input=man_contents)[0]
+        return output
 
     def _send_output_to_pager(self, output):
         cmdline = self.get_pager_cmdline()


Test patch:
diff --git a/tests/unit/test_help.py b/tests/unit/test_help.py
index 3861b4601..8727309cf 100644
--- a/tests/unit/test_help.py
+++ b/tests/unit/test_help.py
@@ -96,13 +96,25 @@ class TestHelpPager(unittest.TestCase):
                          pager_cmd.split())
 
     @skip_if_windows('Requires posix system.')
-    def test_no_groff_exists(self):
+    def test_no_groff_or_mandoc_exists(self):
         renderer = FakePosixHelpRenderer()
         renderer.exists_on_path['groff'] = False
-        expected_error = 'Could not find executable named "groff"'
+        renderer.exists_on_path['mandoc'] = False
+        expected_error = 'Could not find executable named "groff or mandoc"'
         with self.assertRaisesRegex(ExecutableNotFoundError, expected_error):
             renderer.render('foo')
 
+    @skip_if_windows('Requires POSIX system.')
+    def test_renderer_falls_back_to_mandoc(self):
+        stdout = six.StringIO()
+        renderer = FakePosixHelpRenderer(output_stream=stdout)
+
+        renderer.exists_on_path['groff'] = False
+        renderer.exists_on_path['mandoc'] = True
+        renderer.mock_popen.communicate.return_value = (b'foo', '')
+        renderer.render('foo')
+        self.assertEqual(stdout.getvalue(), 'foo\n')
+
     @skip_if_windows('Requires POSIX system.')
     def test_no_pager_exists(self):
         fake_pager = 'foobar'