diff --git a/changelog.rst b/changelog.rst index 96eefd74..1f9190cf 100644 --- a/changelog.rst +++ b/changelog.rst @@ -9,6 +9,12 @@ Features: * Support dsn specific init-command in the config file * Add suggestion when setting the search_path * Allow per dsn_alias ssh tunnel selection +* Add support for `--tuples-only` (`-t`) option to print rows without extra output. + * Similar to psql's `-t` flag + * Command line option `-t` or `--tuples-only` + * Defaults to `csv-noheader` format when used as flag + * Can specify custom format: `-t minimal`, `-t tsv`, etc. + * Suppresses status messages and timing information Internal: --------- diff --git a/pgcli/main.py b/pgcli/main.py index 0b4b64f5..5edeeb15 100644 --- a/pgcli/main.py +++ b/pgcli/main.py @@ -117,7 +117,7 @@ OutputSettings = namedtuple( "OutputSettings", - "table_format dcmlfmt floatfmt column_date_formats missingval expanded max_width case_function style_output max_field_width", + "table_format dcmlfmt floatfmt column_date_formats missingval expanded max_width case_function style_output max_field_width tuples_only", ) OutputSettings.__new__.__defaults__ = ( None, @@ -130,6 +130,7 @@ lambda x: x, None, DEFAULT_MAX_FIELD_WIDTH, + False, ) @@ -179,6 +180,7 @@ def __init__( application_name="pgcli", single_connection=False, less_chatty=None, + tuples_only=None, prompt=None, prompt_dsn=None, auto_vertical_output=False, @@ -235,7 +237,13 @@ def __init__( self.min_num_menu_lines = c["main"].as_int("min_num_menu_lines") self.multiline_continuation_char = c["main"]["multiline_continuation_char"] - self.table_format = c["main"]["table_format"] + # Override table_format if tuples_only is specified + if tuples_only: + self.table_format = tuples_only + self.tuples_only = True + else: + self.table_format = c["main"]["table_format"] + self.tuples_only = False self.syntax_style = c["main"]["syntax_style"] self.cli_style = c["colors"] self.wider_completion_menu = c["main"].as_bool("wider_completion_menu") @@ -850,7 +858,7 @@ def execute_command(self, text, handle_closed_connection=True): except KeyboardInterrupt: pass - if self.pgspecial.timing_enabled: + if self.pgspecial.timing_enabled and not self.tuples_only: # Only add humanized time display if > 1 second if query.total_time > 1: print( @@ -1135,6 +1143,7 @@ def _evaluate_command(self, text): case_function=(self.completer.case if self.settings["case_column_headers"] else lambda x: x), style_output=self.style_output, max_field_width=self.max_field_width, + tuples_only=self.tuples_only, ) execution = time() - start formatted = format_output(title, cur, headers, status, settings, self.explain_mode) @@ -1381,6 +1390,15 @@ def echo_via_pager(self, text, color=None): default=False, help="Skip intro on startup and goodbye on exit.", ) +@click.option( + "-t", + "--tuples-only", + "tuples_only", + is_flag=False, + flag_value="csv-noheader", + default=None, + help="Print rows only (default: csv-noheader). Optionally specify a format (e.g., -t minimal).", +) @click.option("--prompt", help='Prompt format (Default: "\\u@\\h:\\d> ").') @click.option( "--prompt-dsn", @@ -1444,6 +1462,7 @@ def cli( row_limit, application_name, less_chatty, + tuples_only, prompt, prompt_dsn, list_databases, @@ -1506,6 +1525,7 @@ def cli( application_name=application_name, single_connection=single_connection, less_chatty=less_chatty, + tuples_only=tuples_only, prompt=prompt, prompt_dsn=prompt_dsn, auto_vertical_output=auto_vertical_output, @@ -1893,8 +1913,8 @@ def format_status(cur, status): output = itertools.chain(output, formatted) - # Only print the status if it's not None - if status: + # Only print the status if it's not None and tuples_only is not enabled + if status and not settings.tuples_only: output = itertools.chain(output, [format_status(cur, status)]) return output