summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIryna Cherniavska <i.chernyavska@gmail.com>2015-04-21 16:04:13 -0700
committerAmjith Ramanujam <amjith.r@gmail.com>2015-04-22 13:17:08 -0700
commit4231545763c07a7878197a2792a3a52e7bfbf13d (patch)
tree9054d37137387083495cf02b6f9c314c40d2980f
parent4006c6d0cfa5a197710250f6b6e20837892875c3 (diff)
Moved editor command into a separate module.
-rwxr-xr-xpgcli/main.py6
-rw-r--r--pgcli/packages/iospecial.py45
-rw-r--r--pgcli/packages/pgspecial.py37
-rw-r--r--pgcli/pgexecute.py8
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)