diff options
author | Iryna Cherniavska <i.chernyavska@gmail.com> | 2015-04-21 16:04:13 -0700 |
---|---|---|
committer | Amjith Ramanujam <amjith.r@gmail.com> | 2015-04-22 13:17:08 -0700 |
commit | 4231545763c07a7878197a2792a3a52e7bfbf13d (patch) | |
tree | 9054d37137387083495cf02b6f9c314c40d2980f | |
parent | 4006c6d0cfa5a197710250f6b6e20837892875c3 (diff) |
Moved editor command into a separate module.
-rwxr-xr-x | pgcli/main.py | 6 | ||||
-rw-r--r-- | pgcli/packages/iospecial.py | 45 | ||||
-rw-r--r-- | pgcli/packages/pgspecial.py | 37 | ||||
-rw-r--r-- | pgcli/pgexecute.py | 8 |
4 files changed, 61 insertions, 35 deletions
diff --git a/pgcli/main.py b/pgcli/main.py index 561cc41c..59504caf 100755 --- a/pgcli/main.py +++ b/pgcli/main.py @@ -23,6 +23,7 @@ from .packages.expanded import expanded_table from .packages.pgspecial import (CASE_SENSITIVE_COMMANDS, NON_CASE_SENSITIVE_COMMANDS, is_expanded_output) import pgcli.packages.pgspecial as pgspecial +import pgcli.packages.iospecial as iospecial from .pgcompleter import PGCompleter from .pgtoolbar import PGToolbar from .pgstyle import style_factory @@ -199,7 +200,7 @@ class PGCli(object): # Editor command is a special case. We don't have to execute it # and print out the result. We have to extend our output and # continue typing in SQL / commands. - if editor_command(document.text): + if iospecial.editor_command(document.text): sql, _, _, message = list(pgexecute.run(document.text))[0] if sql or not message: # We either have some SQL, or no SQL, but no error @@ -430,9 +431,6 @@ def is_select(status): return False return status.split(None, 1)[0].lower() == 'select' -def editor_command(sql): - return sql.strip().startswith('\e') - def quit_command(sql): return (sql.strip().lower() == 'exit' or sql.strip().lower() == 'quit' diff --git a/pgcli/packages/iospecial.py b/pgcli/packages/iospecial.py new file mode 100644 index 00000000..82ed9f0d --- /dev/null +++ b/pgcli/packages/iospecial.py @@ -0,0 +1,45 @@ +from __future__ import print_function + + +import logging +import click + +_logger = logging.getLogger(__name__) + + +def editor_command(command): + """ + Is this an external editor command? + :param command: string + """ + return command.strip().startswith('\e') + + +def open_external_editor(filename=None): + """ + Open external editor, wait for the user to type in his query, + return the query. + :return: list with one tuple, query as first element. + """ + + message = None + filename = filename.strip().split(' ', 1)[0] if filename else None + + MARKER = '# Type your query above this line.\n' + query = click.edit('\n\n' + MARKER, filename=filename) + + if filename: + try: + with open(filename, "r") as f: + query = f.read() + except IOError: + message = 'Error reading file: %s.' % filename + + if query is not None: + query = query.split(MARKER, 1)[0].rstrip('\n') + else: + # Don't return None for the caller to deal with. + # Empty string is ok. + query = '' + + yield (query, None, None, message) diff --git a/pgcli/packages/pgspecial.py b/pgcli/packages/pgspecial.py index 2c7d2e8c..57897b01 100644 --- a/pgcli/packages/pgspecial.py +++ b/pgcli/packages/pgspecial.py @@ -1,7 +1,6 @@ from __future__ import print_function import sys import logging -import click from collections import namedtuple from .tabulate import tabulate @@ -929,37 +928,15 @@ def show_help(cur, arg, verbose): # All the parameters are ignored. result.append(value[1]) return [(None, result, headers, None)] -def change_db(cur, arg, verbose): - raise NotImplementedError -def open_external_editor(cur, arg, verbose): +def dummy_command(cur, arg, verbose): """ - Open external editor, wait for the user to type in his query, - return the query. - :return: list with one tuple, query as first element. + Used by commands that are actually handled elsewhere. + But we want to keep their docstrings in the same list + as all the rest of commands. """ + raise NotImplementedError - message = None - filename = arg.strip().split(' ', 1)[0] if arg else None - - MARKER = '# Type your query above this line.\n' - query = click.edit('\n\n' + MARKER, filename=filename) - - if filename: - try: - with open(filename, "r") as f: - query = f.read() - except IOError: - message = 'Error reading file: %s.' % filename - - if query is not None: - query = query.split(MARKER, 1)[0].rstrip('\n') - else: - # Don't return None for the caller to deal with. - # Empty string is ok. - query = '' - - return [(query, None, None, message)] def in_progress(cur, arg, verbose): """ @@ -983,7 +960,7 @@ def toggle_timing(cur, arg, verbose): CASE_SENSITIVE_COMMANDS = { '\?': (show_help, ['\?', 'Help on pgcli commands.']), - '\c': (change_db, ['\c database_name', 'Connect to a new database.']), + '\c': (dummy_command, ['\c database_name', 'Connect to a new database.']), '\l': ('''SELECT datname FROM pg_database;''', ['\l', 'List databases.']), '\d': (describe_table_details, ['\d [pattern]', 'List or describe tables, views and sequences.']), '\dn': (list_schemas, ['\dn[+] [pattern]', 'List schemas.']), @@ -995,7 +972,7 @@ CASE_SENSITIVE_COMMANDS = { '\\dv': (list_views, ['\\dv[+] [pattern]', 'List views.']), '\\ds': (list_sequences, ['\\ds[+] [pattern]', 'List sequences.']), '\\df': (list_functions, ['\\df[+] [pattern]', 'List functions.']), - '\e': (open_external_editor, ['\e [file]', 'Edit the query buffer (or file) with external editor.']), + '\e': (dummy_command, ['\e [file]', 'Edit the query buffer (or file) with external editor.']), '\ef': (in_progress, ['\ef [funcname [line]]', 'Not yet implemented.']), '\sf': (in_progress, ['\sf[+] funcname', 'Not yet implemented.']), '\z': (in_progress, ['\z [pattern]', 'Not yet implemented.']), diff --git a/pgcli/pgexecute.py b/pgcli/pgexecute.py index c293bb2c..3dc4cc4f 100644 --- a/pgcli/pgexecute.py +++ b/pgcli/pgexecute.py @@ -4,6 +4,7 @@ import psycopg2.extras import psycopg2.extensions as ext import sqlparse from .packages import pgspecial +from .packages import iospecial from .encodingutils import unicode2utf8, PY2, PY3 _logger = logging.getLogger(__name__) @@ -160,7 +161,7 @@ class PGExecute(object): def run(self, statement): """Execute the sql in the database and return the results. The results - are a list of tuples. Each tuple has 3 values (rows, headers, status). + are a list of tuples. Each tuple has 4 values (title, rows, headers, status). """ # Remove spaces and EOL @@ -189,6 +190,11 @@ class PGExecute(object): _logger.debug('Successfully switched to DB: %r', dbname) yield (None, None, None, 'You are now connected to database "%s" as ' 'user "%s"' % (self.dbname, self.user)) + elif iospecial.editor_command(command): + tokens = sql.split(' ', 2) + filename = tokens[1] if len(tokens) > 1 and tokens[1] else None + for result in iospecial.open_external_editor(filename=filename): + yield result else: try: # Special command _logger.debug('Trying a pgspecial command. sql: %r', sql) |