1
0
mirror of https://github.com/httpie/cli.git synced 2025-08-10 22:42:05 +02:00

Man page fixes (#1364)

- Highlighting for options (-x, --x) now doesn't strip the prefix (may be whitespace).
- Escape sequences are now cross-platform compatible (directly taken by groff/troff [man's renderer])
- Now we check for the section before displaying the man pages.
- On MacOS, there is HTTP(n) which is different from our HTTP(1). This used to conflict with it, and we showed the wrong page. Now we specifically ask foir HTTP(1).
- Errors that might happen (e.g non executable man command) is now suppressed. So in the worst case (if anything regarding man execution goes wrong), we'll always display the manual.
- Docs for man pages.
- HTTPie man pages.
- Epilog for the man pages (see also)
- Auto-generated comments.
This commit is contained in:
Batuhan Taskaya
2022-05-05 21:17:37 +03:00
committed by GitHub
parent 76495cbdec
commit f9b5c2f696
13 changed files with 280 additions and 204 deletions

View File

@@ -26,16 +26,13 @@ options = ParserSpec(
'http',
description=f'{__doc__.strip()} <https://httpie.io>',
epilog="""
To learn more, you can try:
-> running 'http --manual'
-> visiting our full documentation at https://httpie.io/docs/cli
For every --OPTION there is also a --no-OPTION that reverts OPTION
to its default value.
Suggestions and bug reports are greatly appreciated:
https://github.com/httpie/httpie/issues
""",
source_file=__file__
)

View File

@@ -35,17 +35,6 @@ def drop_keys(
}
def _get_first_line(source: str) -> str:
parts = []
for line in source.strip().splitlines():
line = line.strip()
parts.append(line)
if line.endswith("."):
break
return " ".join(parts)
PARSER_SPEC_VERSION = '0.0.1a0'
@@ -55,6 +44,8 @@ class ParserSpec:
description: Optional[str] = None
epilog: Optional[str] = None
groups: List['Group'] = field(default_factory=list)
man_page_hint: Optional[str] = None
source_file: Optional[str] = None
def finalize(self) -> 'ParserSpec':
if self.description:
@@ -248,10 +239,11 @@ def to_data(abstract_options: ParserSpec) -> Dict[str, Any]:
return {'version': PARSER_SPEC_VERSION, 'spec': abstract_options.serialize()}
def parser_to_parser_spec(parser: argparse.ArgumentParser) -> ParserSpec:
def parser_to_parser_spec(parser: argparse.ArgumentParser, **kwargs) -> ParserSpec:
"""Take an existing argparse parser, and create a spec from it."""
return ParserSpec(
program=parser.prog,
description=parser.description,
epilog=parser.epilog
epilog=parser.epilog,
**kwargs
)

View File

@@ -20,6 +20,7 @@ COMMANDS = {
{
'flags': ['-f', '--format'],
'choices': ['json'],
'help': 'Format to export in.',
'default': 'json'
}
],
@@ -166,5 +167,12 @@ parser.add_argument(
'''
)
options = parser_to_parser_spec(parser)
man_page_hint = '''
If you are looking for the man pages of http/https commands, try one of the following:
$ man http
$ man https
'''
options = parser_to_parser_spec(parser, man_page_hint=man_page_hint, source_file=__file__)
generate_subparsers(parser, parser, COMMANDS, options)

View File

@@ -7,6 +7,13 @@ from httpie.context import Environment
MAN_COMMAND = 'man'
NO_MAN_PAGES = os.getenv('HTTPIE_NO_MAN_PAGES', False)
# On some systems, HTTP(n) might exist but we are only
# interested in HTTP(1).
#
# For more information on man page sections: https://unix.stackexchange.com/a/138643
MAN_PAGE_SECTION = '1'
def is_available(program: str) -> bool:
"""Check whether HTTPie's man pages are available in this system."""
@@ -14,18 +21,27 @@ def is_available(program: str) -> bool:
if NO_MAN_PAGES or os.system == 'nt':
return False
process = subprocess.run(
[MAN_COMMAND, program],
shell=False,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
return process.returncode == 0
try:
process = subprocess.run(
[MAN_COMMAND, MAN_PAGE_SECTION, program],
shell=False,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
except Exception:
# There might be some errors outside of the process, e.g
# a permission error to execute something that is not an
# executable.
return False
else:
return process.returncode == 0
def display_for(env: Environment, program: str) -> None:
"""Display the man page for the given command (http/https)."""
subprocess.run(
[MAN_COMMAND, program], stdout=env.stdout, stderr=env.stderr
[MAN_COMMAND, MAN_PAGE_SECTION, program],
stdout=env.stdout,
stderr=env.stderr
)

View File

@@ -26,6 +26,7 @@ STYLE_BOLD = 'bold'
MAX_CHOICE_CHARS = 80
LEFT_PADDING_2 = (0, 0, 0, 2)
LEFT_PADDING_3 = (0, 0, 0, 3)
LEFT_PADDING_4 = (0, 0, 0, 4)
LEFT_PADDING_5 = (0, 0, 0, 4)
@@ -33,6 +34,12 @@ LEFT_INDENT_2 = (1, 0, 0, 2)
LEFT_INDENT_3 = (1, 0, 0, 3)
LEFT_INDENT_BOTTOM_3 = (0, 0, 1, 3)
MORE_INFO_COMMANDS = """
To learn more, you can try:
-> running 'http --manual'
-> visiting our full documentation at https://httpie.io/docs/cli
"""
class OptionsHighlighter(RegexHighlighter):
highlights = [
@@ -213,6 +220,10 @@ def to_help_message(
Text('More Information', style=STYLE_SWITCH),
LEFT_INDENT_2,
)
yield Padding(
MORE_INFO_COMMANDS.rstrip('\n'),
LEFT_PADDING_3
)
yield Padding(
spec.epilog.rstrip('\n'),
LEFT_INDENT_BOTTOM_3,

View File

@@ -42,7 +42,7 @@ class _GenericColorCaster(dict):
return super().get(self._translate(key))
def _make_rich_color_theme(style_name: Optional[str]) -> 'Theme':
def _make_rich_color_theme(style_name: Optional[str] = None) -> 'Theme':
from rich.style import Style
from rich.theme import Theme

View File

@@ -6,13 +6,15 @@ from contextlib import contextmanager
from rich.console import Console, RenderableType
from rich.highlighter import Highlighter
from httpie.output.ui.rich_palette import _make_rich_color_theme
def render_as_string(renderable: RenderableType) -> str:
"""Render any `rich` object in a fake console and
return a *style-less* version of it as a string."""
with open(os.devnull, 'w') as null_stream:
fake_console = Console(file=null_stream, record=True)
fake_console = Console(file=null_stream, record=True, theme=_make_rich_color_theme())
fake_console.print(renderable)
return fake_console.export_text()