summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO8
-rw-r--r--pgcli/packages/pgspecial.py25
-rw-r--r--pgcli/pgcompleter.py2
-rw-r--r--pgcli/pgexecute.py14
4 files changed, 32 insertions, 17 deletions
diff --git a/TODO b/TODO
index cddb23e8..67f835e5 100644
--- a/TODO
+++ b/TODO
@@ -1,21 +1,21 @@
+* [O] Add MySQL commands (use, describe etc)
* [] Check why Indexes have a invalid at the end when \d is called on them.
-* [] Fix smartcompletion for special commands. \d <tab>
* [] Add some tests. Sanity, Unit, Completion, Config.
* [ ] Add tests for smart completion.
* [] Check how to add the name of the table before printing the table.
* [] Show only table sensitive columns in autocompletion.
-* [] Add a toolbar at the bottom with some helpful keyboard shortcuts.
* [] Add logging.
* [] Setup the pgcli.com website.
* [ ] Add a new trigger for M-/ that does dumb completion.
-* [] Add function keys that can enable/disable smart completion.
* [] Improve the smart completion for Insert statement.
* [] Improve the smart completion for Update statement.
* [ ] Find a way to add documentation to sql commands. This could get tricky.
* [ ] Detect a '.' and parse the word before it and get it's real name.
* [] Refactor the execution and output into a separate class.
* [] Create a class for the config and make it easy to access.
-* [O] Add MySQL commands (use, describe etc)
+* [X] Add function keys that can enable/disable smart completion.
+* [X] Add a toolbar at the bottom with some helpful keyboard shortcuts.
+* [X] Fix smartcompletion for special commands. \d <tab>
* [X] Add more complex slash commands such as \d <table_name>.
* This is going to take a separate lib.
* [X] Create a better framework for adding special commands.
diff --git a/pgcli/packages/pgspecial.py b/pgcli/packages/pgspecial.py
index 39b28f55..4f647eff 100644
--- a/pgcli/packages/pgspecial.py
+++ b/pgcli/packages/pgspecial.py
@@ -19,6 +19,24 @@ class MockLogging(object):
#log = MockLogging()
+#def parse_special_command(sql):
+
+ ## Sort the command by the length, so the longest command comes first. This
+ ## is to ensure we match the most specific command first. For example: \dt+
+ ## will match \dt instead of \d.
+ #ordered_commands = sorted(COMMANDS, key=len, reverse=True)
+ #for command in ordered_commands:
+ #if sql.startswith(command):
+ #plus, _, arg = sql[len(command):].partition(' ')
+ #break
+ #verbose = '+' in plus
+ #return (command.strip(), verbose, arg.strip())
+
+def parse_special_command(sql):
+ command, _, arg = sql.partition(' ')
+ verbose = '+' in command
+ return (command.strip(), verbose, arg.strip())
+
def describe_table_details(cur, pattern, verbose):
"""
Returns (rows, headers, status)
@@ -670,6 +688,7 @@ def sql_name_pattern(pattern):
return schema, relname
COMMANDS = {
+ 'describe': describe_table_details,
'\d': describe_table_details,
'\dt': '''SELECT n.nspname as "Schema", c.relname as "Name", CASE
c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN
@@ -683,12 +702,12 @@ COMMANDS = {
1,2;'''
}
-command_available = COMMANDS.__contains__
-
-def execute(cur, command, verbose, arg):
+def execute(cur, sql):
"""Execute a special command and return the results. If the special command
is not supported a KeyError will be raised.
"""
+ command, verbose, arg = parse_special_command(sql)
+
global COMMANDS
command_executor = COMMANDS[command]
diff --git a/pgcli/pgcompleter.py b/pgcli/pgcompleter.py
index 5d4f879e..9a2cb4db 100644
--- a/pgcli/pgcompleter.py
+++ b/pgcli/pgcompleter.py
@@ -94,7 +94,7 @@ class PGCompleter(Completer):
return self.find_matches(word_before_cursor, self.column_names)
elif last_token.lower() in ('from', 'update', 'into'):
return self.find_matches(word_before_cursor, self.table_names)
- elif last_token in ('d',): # This for the \d special command.
+ elif last_token in ('d', 'describe'): # This for the \d special command.
return self.find_matches(word_before_cursor, self.table_names)
elif last_token in ('c',): # This for the \c special command.
return self.find_matches(word_before_cursor, self.database_names)
diff --git a/pgcli/pgexecute.py b/pgcli/pgexecute.py
index e24741ba..a043e187 100644
--- a/pgcli/pgexecute.py
+++ b/pgcli/pgexecute.py
@@ -24,12 +24,6 @@ class PGExecute(object):
self.port = port
self.conn.autocommit = True
- @staticmethod
- def parse_pattern(sql):
- command, _, arg = sql.partition(' ')
- verbose = '+' in command
- return (command.strip(), verbose, arg.strip())
-
def run(self, sql):
"""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).
@@ -43,7 +37,10 @@ class PGExecute(object):
# that cannot be offloaded to `pgspecial` lib. Because we have to
# change the database connection that we're connected to.
if sql.startswith('\c') or sql.lower().startswith('use'):
- dbname = self.parse_pattern(sql)[2]
+ try:
+ dbname = sql.split()[1]
+ except:
+ raise RuntimeError('Database name missing.')
self.conn = psycopg2.connect(database=dbname,
user=self.user, password=self.password, host=self.host,
port=self.port)
@@ -53,8 +50,7 @@ class PGExecute(object):
with self.conn.cursor() as cur:
try:
- results = pgspecial.execute(cur, *self.parse_pattern(sql))
- return results
+ return pgspecial.execute(cur, sql)
except KeyError:
cur.execute(sql)