diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 54b8c623..3c9b9125 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,6 +11,7 @@ This project adheres to `Semantic Versioning `_.
* Fixed built-in plugins-related circular imports (`#925`_).
* Added ``--format-options`` to allow disabling sorting, etc. (`#128`_)
+* Added ``--unsorted`` shortcut to set all sorting-related ``--format-options`` to ``false``. (`#128`_)
* Added ``--ciphers`` to allow configuring OpenSSL ciphers (`#870`_).
* Added support for ``$XDG_CONFIG_HOME`` (`#920`_).
* Added support for custom content types for uploaded files (`#668`_).
diff --git a/httpie/cli/argparser.py b/httpie/cli/argparser.py
index 37bb170e..b99d38be 100644
--- a/httpie/cli/argparser.py
+++ b/httpie/cli/argparser.py
@@ -9,9 +9,14 @@ from urllib.parse import urlsplit
from requests.utils import get_netrc_auth
-from httpie.cli.argtypes import AuthCredentials, KeyValueArgType, parse_auth
+from httpie.cli.argtypes import (
+ AuthCredentials, KeyValueArgType, PARSED_DEFAULT_FORMAT_OPTIONS,
+ parse_auth,
+ parse_format_options,
+)
from httpie.cli.constants import (
- HTTP_GET, HTTP_POST, OUTPUT_OPTIONS, OUTPUT_OPTIONS_DEFAULT,
+ DEFAULT_FORMAT_OPTIONS, HTTP_GET, HTTP_POST, OUTPUT_OPTIONS,
+ OUTPUT_OPTIONS_DEFAULT,
OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED, OUT_RESP_BODY, PRETTY_MAP,
PRETTY_STDOUT_TTY_ONLY, SEPARATOR_CREDENTIALS, SEPARATOR_GROUP_ALL_ITEMS,
SEPARATOR_GROUP_DATA_ITEMS, URL_SCHEME_RE,
@@ -44,6 +49,8 @@ class HTTPieHelpFormatter(RawDescriptionHelpFormatter):
return text.splitlines()
+# TODO: refactor and design type-annotated data structures
+# for raw args + parsed args and keep things immutable.
class HTTPieArgumentParser(argparse.ArgumentParser):
"""Adds additional logic to `argparse.ArgumentParser`.
@@ -84,6 +91,7 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
self._setup_standard_streams()
self._process_output_options()
self._process_pretty_options()
+ self._process_format_options()
self._guess_method()
self._parse_items()
@@ -405,3 +413,9 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
if self.args.download_resume and not (
self.args.download and self.args.output_file):
self.error('--continue requires --output to be specified')
+
+ def _process_format_options(self):
+ parsed_options = PARSED_DEFAULT_FORMAT_OPTIONS
+ for options_group in self.args.format_options:
+ parsed_options = parse_format_options(options_group, defaults=parsed_options)
+ self.args.format_options = parsed_options
diff --git a/httpie/cli/argtypes.py b/httpie/cli/argtypes.py
index 0d4f9eb2..4f16e7c4 100644
--- a/httpie/cli/argtypes.py
+++ b/httpie/cli/argtypes.py
@@ -242,3 +242,9 @@ PARSED_DEFAULT_FORMAT_OPTIONS = parse_format_options(
s=','.join(DEFAULT_FORMAT_OPTIONS),
defaults=None,
)
+
+
+class UnsortedAction(argparse.Action):
+
+ def __call__(self, *args, **kwargs):
+ return 1
diff --git a/httpie/cli/constants.py b/httpie/cli/constants.py
index ea8036fe..6305588c 100644
--- a/httpie/cli/constants.py
+++ b/httpie/cli/constants.py
@@ -91,7 +91,10 @@ DEFAULT_FORMAT_OPTIONS = [
'json.indent:4',
'json.sort_keys:true',
]
-
+UNSORTED_FORMAT_OPTIONS = [
+ 'headers.sort:false',
+ 'json.sort_keys:false',
+]
# Defaults
OUTPUT_OPTIONS_DEFAULT = OUT_RESP_HEAD + OUT_RESP_BODY
diff --git a/httpie/cli/definition.py b/httpie/cli/definition.py
index b3b5f388..f8215220 100644
--- a/httpie/cli/definition.py
+++ b/httpie/cli/definition.py
@@ -9,14 +9,13 @@ from httpie import __doc__, __version__
from httpie.cli.argparser import HTTPieArgumentParser
from httpie.cli.argtypes import (
KeyValueArgType, PARSED_DEFAULT_FORMAT_OPTIONS, SessionNameValidator,
- parse_format_options,
readable_file_arg,
)
from httpie.cli.constants import (
DEFAULT_FORMAT_OPTIONS, OUTPUT_OPTIONS,
OUTPUT_OPTIONS_DEFAULT, OUT_REQ_BODY, OUT_REQ_HEAD,
OUT_RESP_BODY, OUT_RESP_HEAD, PRETTY_MAP, PRETTY_STDOUT_TTY_ONLY,
- SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_PROXY,
+ SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_PROXY, UNSORTED_FORMAT_OPTIONS,
)
from httpie.output.formatters.colors import (
AUTO_STYLE, AVAILABLE_STYLES, DEFAULT_STYLE,
@@ -229,14 +228,22 @@ output_processing.add_argument(
auto_style=AUTO_STYLE,
)
)
+output_processing.add_argument(
+ '--unsorted',
+ action='append_const',
+ const=','.join(UNSORTED_FORMAT_OPTIONS),
+ dest='format_options',
+ help="""
+ Disables all sorting while formatting output. It is a shortcut for:
+ --format-options=json.sort_keys:false,headers.sort:false
+
+ """
+)
output_processing.add_argument(
'--format-options',
- type=lambda s: parse_format_options(
- s=s,
- defaults=PARSED_DEFAULT_FORMAT_OPTIONS
- ),
- default=PARSED_DEFAULT_FORMAT_OPTIONS,
+ default=[],
+ action='append',
help="""
Controls output formatting. Only relevant when formatting is enabled
through (explicit or implied) --pretty=all or --pretty=format.
@@ -244,10 +251,11 @@ output_processing.add_argument(
{option_list}
- You can specify multiple comma-separated options. For example, this modifies
- the settings to disable the sorting of JSON keys and headers:
+ You may use this option multiple times, as well as specify multiple
+ comma-separated options at the same time. For example, this modifies the
+ settings to disable the sorting of JSON keys, and sets the indent size to 2:
- --format-options json.sort_keys:false,headers.sort:false
+ --format-options json.sort_keys:false,json.indent:2
This is something you will typically put into your config file.
diff --git a/tests/test_output.py b/tests/test_output.py
index e0438c10..afa499ce 100644
--- a/tests/test_output.py
+++ b/tests/test_output.py
@@ -6,7 +6,12 @@ from urllib.request import urlopen
import pytest
-from httpie.cli.argtypes import parse_format_options
+from httpie.cli.constants import DEFAULT_FORMAT_OPTIONS
+from httpie.cli.definition import parser
+from httpie.cli.argtypes import (
+ PARSED_DEFAULT_FORMAT_OPTIONS,
+ parse_format_options,
+)
from httpie.output.formatters.colors import get_lexer
from httpie.status import ExitStatus
from utils import COLOR, CRLF, HTTP_OK, MockEnvironment, http
@@ -249,3 +254,55 @@ class TestFormatOptions:
}
with pytest.raises(argparse.ArgumentTypeError, match=expected_error):
parse_format_options(s=options_string, defaults=defaults)
+
+ @pytest.mark.parametrize(
+ argnames=['args', 'expected_format_options'],
+ argvalues=[
+ (
+ [
+ '--format-options',
+ 'headers.sort:false,json.sort_keys:false',
+ '--format-options=json.indent:10'
+ ],
+ {
+ 'headers': {'sort': False},
+ 'json': {'sort_keys': False, 'indent': 10, 'format': True},
+ }
+ ),
+ (
+ [
+ '--unsorted'
+ ],
+ {
+ 'headers': {'sort': False},
+ 'json': {'sort_keys': False, 'indent': 4, 'format': True},
+ }
+ ),
+ (
+ [
+ '--format-options=headers.sort:true',
+ '--unsorted',
+ '--format-options=headers.sort:true',
+ ],
+ {
+ 'headers': {'sort': True},
+ 'json': {'sort_keys': False, 'indent': 4, 'format': True},
+ }
+ ),
+ (
+ [
+ '--no-format-options', # --no-