summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Slenders <jonathan@slenders.be>2018-05-24 22:26:59 +0200
committerJonathan Slenders <jonathan@slenders.be>2018-05-24 22:30:48 +0200
commit24512aac081d1e30ad52805606b42411f1aed861 (patch)
tree7335c2b855da62ec8e0a65147e12d344fe61da2e
parent1d3991df3305ee20534326efdd433e021650c642 (diff)
Updated SQLite tutorial with new images and small improvements.
-rw-r--r--docs/images/repl/1.pngbin70421 -> 0 bytes
-rw-r--r--docs/images/repl/2.pngbin85031 -> 0 bytes
-rw-r--r--docs/images/repl/3.pngbin75365 -> 0 bytes
-rw-r--r--docs/images/repl/4.pngbin61473 -> 0 bytes
-rw-r--r--docs/images/repl/5.pngbin67403 -> 0 bytes
-rw-r--r--docs/images/repl/6.pngbin47881 -> 0 bytes
-rw-r--r--docs/images/repl/sqlite-1.pngbin0 -> 125880 bytes
-rw-r--r--docs/images/repl/sqlite-2.pngbin0 -> 171192 bytes
-rw-r--r--docs/images/repl/sqlite-3.pngbin0 -> 126517 bytes
-rw-r--r--docs/images/repl/sqlite-4.pngbin0 -> 190998 bytes
-rw-r--r--docs/images/repl/sqlite-5.pngbin0 -> 182631 bytes
-rw-r--r--docs/images/repl/sqlite-6.pngbin0 -> 200352 bytes
-rw-r--r--docs/pages/tutorials/repl.rst116
-rwxr-xr-xexamples/tutorial/sqlite-cli.py35
-rw-r--r--prompt_toolkit/layout/controls.py2
15 files changed, 116 insertions, 37 deletions
diff --git a/docs/images/repl/1.png b/docs/images/repl/1.png
deleted file mode 100644
index 63362c23..00000000
--- a/docs/images/repl/1.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/2.png b/docs/images/repl/2.png
deleted file mode 100644
index f9ddb100..00000000
--- a/docs/images/repl/2.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/3.png b/docs/images/repl/3.png
deleted file mode 100644
index e62264da..00000000
--- a/docs/images/repl/3.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/4.png b/docs/images/repl/4.png
deleted file mode 100644
index 0e75323c..00000000
--- a/docs/images/repl/4.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/5.png b/docs/images/repl/5.png
deleted file mode 100644
index 3c0f159a..00000000
--- a/docs/images/repl/5.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/6.png b/docs/images/repl/6.png
deleted file mode 100644
index d3405cc0..00000000
--- a/docs/images/repl/6.png
+++ /dev/null
Binary files differ
diff --git a/docs/images/repl/sqlite-1.png b/docs/images/repl/sqlite-1.png
new file mode 100644
index 00000000..0511daa0
--- /dev/null
+++ b/docs/images/repl/sqlite-1.png
Binary files differ
diff --git a/docs/images/repl/sqlite-2.png b/docs/images/repl/sqlite-2.png
new file mode 100644
index 00000000..47b02382
--- /dev/null
+++ b/docs/images/repl/sqlite-2.png
Binary files differ
diff --git a/docs/images/repl/sqlite-3.png b/docs/images/repl/sqlite-3.png
new file mode 100644
index 00000000..cdee9d20
--- /dev/null
+++ b/docs/images/repl/sqlite-3.png
Binary files differ
diff --git a/docs/images/repl/sqlite-4.png b/docs/images/repl/sqlite-4.png
new file mode 100644
index 00000000..c6ee9297
--- /dev/null
+++ b/docs/images/repl/sqlite-4.png
Binary files differ
diff --git a/docs/images/repl/sqlite-5.png b/docs/images/repl/sqlite-5.png
new file mode 100644
index 00000000..d1964e02
--- /dev/null
+++ b/docs/images/repl/sqlite-5.png
Binary files differ
diff --git a/docs/images/repl/sqlite-6.png b/docs/images/repl/sqlite-6.png
new file mode 100644
index 00000000..054beb05
--- /dev/null
+++ b/docs/images/repl/sqlite-6.png
Binary files differ
diff --git a/docs/pages/tutorials/repl.rst b/docs/pages/tutorials/repl.rst
index 6aac7a51..7d7bba13 100644
--- a/docs/pages/tutorials/repl.rst
+++ b/docs/pages/tutorials/repl.rst
@@ -33,7 +33,7 @@ function as a good practise.
if __name__ == '__main__':
main()
-.. image:: ../../images/repl/1.png
+.. image:: ../../images/repl/sqlite-1.png
Loop The REPL
@@ -75,7 +75,7 @@ respectively.
if __name__ == '__main__':
main()
-.. image:: ../../images/repl/2.png
+.. image:: ../../images/repl/sqlite-2.png
Syntax Highlighting
@@ -114,14 +114,15 @@ wrapped into a :class:`~prompt_toolkit.lexers.PygmentsLexer`.
if __name__ == '__main__':
main()
-.. image:: ../../images/repl/3.png
+.. image:: ../../images/repl/sqlite-3.png
Auto-completion
---------------
-Now we are going to add auto completion. We'd like a drop down menu of possible
-keywords when the user is typing.
+Now we are going to add auto completion. We'd like a drop down menu of
+`possible keywords <https://www.sqlite.org/lang_keywords.html>`_ when the user
+is typing.
Create your ``sql_completer`` instance from the ``WordCompleter`` class
defining a set of ``keywords`` for auto-completion.
@@ -138,9 +139,26 @@ Like the lexer, this ``sql_completer`` instance can be passed to either the
from prompt_toolkit.lexers import PygmentsLexer
from pygments.lexers import SqlLexer
- sql_completer = WordCompleter(
- ['create', 'select', 'insert', 'drop', 'delete', 'from', 'where', 'table'],
- ignore_case=True)
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
def main():
session = PromptSession(
@@ -160,7 +178,7 @@ Like the lexer, this ``sql_completer`` instance can be passed to either the
if __name__ == '__main__':
main()
-.. image:: ../../images/repl/4.png
+.. image:: ../../images/repl/sqlite-4.png
In about 30 lines of code we got ourselves an auto completing, syntax
highlighting REPL. Let's make it better.
@@ -183,14 +201,32 @@ function.
from prompt_toolkit.styles import Style
from pygments.lexers import SqlLexer
- sql_completer = WordCompleter(
- ['create', 'select', 'insert', 'drop', 'delete', 'from', 'where', 'table'],
- ignore_case=True)
-
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
style = Style.from_dict({
- 'completion-menu.current-completion': 'bg:#00aaaa #000000',
'completion-menu.completion': 'bg:#008888 #ffffff',
+ 'completion-menu.completion.current': 'bg:#00aaaa #000000',
+ 'scrollbar.background': 'bg:#88aaaa',
+ 'scrollbar.button': 'bg:#222222',
})
def main():
@@ -211,7 +247,7 @@ function.
if __name__ == '__main__':
main()
-.. image:: ../../images/repl/5.png
+.. image:: ../../images/repl/sqlite-5.png
All that's left is hooking up the sqlite backend, which is left as an exercise
for the reader. Just kidding... Keep reading.
@@ -220,49 +256,75 @@ for the reader. Just kidding... Keep reading.
Hook up Sqlite
--------------
-This step is totally optional ;). So far we've been focusing on building the
-REPL. Now it's time to relay the input to SQLite.
+This step is the final step to make the SQLite REPL actually work. It's time
+to relay the input to SQLite.
Obviously I haven't done the due diligence to deal with the errors. But it
gives a good idea of how to get started.
.. code:: python
+ #!/usr/bin/env python
from __future__ import unicode_literals
import sys
import sqlite3
from prompt_toolkit import PromptSession
from prompt_toolkit.completion import WordCompleter
+ from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.styles import Style
from pygments.lexers import SqlLexer
- sql_completer = WordCompleter(
- ['create', 'select', 'insert', 'drop', 'delete', 'from', 'where', 'table'],
- ignore_case=True)
+ sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
style = Style.from_dict({
- 'completion-menu.current-completion': 'bg:#00aaaa #000000',
'completion-menu.completion': 'bg:#008888 #ffffff',
+ 'completion-menu.completion.current': 'bg:#00aaaa #000000',
+ 'scrollbar.background': 'bg:#88aaaa',
+ 'scrollbar.button': 'bg:#222222',
})
def main(database):
connection = sqlite3.connect(database)
session = PromptSession(
- lexer=SqlLexer, completer=sql_completer, style=style)
+ lexer=PygmentsLexer(SqlLexer), completer=sql_completer, style=style)
while True:
try:
text = session.prompt('> ')
except KeyboardInterrupt:
- continue # Control-C pressed. Try again.
+ continue # Control-C pressed. Try again.
except EOFError:
break # Control-D pressed.
with connection:
- messages = connection.execute(text)
- for message in messages:
- print(message)
+ try:
+ messages = connection.execute(text)
+ except Exception as e:
+ print(repr(e))
+ else:
+ for message in messages:
+ print(message)
+
print('GoodBye!')
if __name__ == '__main__':
@@ -273,7 +335,7 @@ gives a good idea of how to get started.
main(db)
-.. image:: ../../images/repl/6.png
+.. image:: ../../images/repl/sqlite-6.png
I hope that gives an idea of how to get started on building command line
interfaces.
diff --git a/examples/tutorial/sqlite-cli.py b/examples/tutorial/sqlite-cli.py
index da9abda9..04cf259e 100755
--- a/examples/tutorial/sqlite-cli.py
+++ b/examples/tutorial/sqlite-cli.py
@@ -1,25 +1,42 @@
#!/usr/bin/env python
-from __future__ import unicode_literals
+from __future__ import unicode_literals, print_function
import sys
import sqlite3
from prompt_toolkit import PromptSession
from prompt_toolkit.completion import WordCompleter
-from prompt_toolkit.styles import Style
from prompt_toolkit.lexers import PygmentsLexer
-
+from prompt_toolkit.styles import Style
from pygments.lexers import SqlLexer
-sql_completer = WordCompleter(
- ['create', 'select', 'insert', 'drop', 'delete', 'from', 'where', 'table'],
- ignore_case=True)
+sql_completer = WordCompleter([
+ 'abort', 'action', 'add', 'after', 'all', 'alter', 'analyze', 'and',
+ 'as', 'asc', 'attach', 'autoincrement', 'before', 'begin', 'between',
+ 'by', 'cascade', 'case', 'cast', 'check', 'collate', 'column',
+ 'commit', 'conflict', 'constraint', 'create', 'cross', 'current_date',
+ 'current_time', 'current_timestamp', 'database', 'default',
+ 'deferrable', 'deferred', 'delete', 'desc', 'detach', 'distinct',
+ 'drop', 'each', 'else', 'end', 'escape', 'except', 'exclusive',
+ 'exists', 'explain', 'fail', 'for', 'foreign', 'from', 'full', 'glob',
+ 'group', 'having', 'if', 'ignore', 'immediate', 'in', 'index',
+ 'indexed', 'initially', 'inner', 'insert', 'instead', 'intersect',
+ 'into', 'is', 'isnull', 'join', 'key', 'left', 'like', 'limit',
+ 'match', 'natural', 'no', 'not', 'notnull', 'null', 'of', 'offset',
+ 'on', 'or', 'order', 'outer', 'plan', 'pragma', 'primary', 'query',
+ 'raise', 'recursive', 'references', 'regexp', 'reindex', 'release',
+ 'rename', 'replace', 'restrict', 'right', 'rollback', 'row',
+ 'savepoint', 'select', 'set', 'table', 'temp', 'temporary', 'then',
+ 'to', 'transaction', 'trigger', 'union', 'unique', 'update', 'using',
+ 'vacuum', 'values', 'view', 'virtual', 'when', 'where', 'with',
+ 'without'], ignore_case=True)
style = Style.from_dict({
- 'completion-menu.current-completion': 'bg:#00aaaa #000000',
'completion-menu.completion': 'bg:#008888 #ffffff',
+ 'completion-menu.completion.current': 'bg:#00aaaa #000000',
+ 'scrollbar.background': 'bg:#88aaaa',
+ 'scrollbar.button': 'bg:#222222',
})
-
def main(database):
connection = sqlite3.connect(database)
session = PromptSession(
@@ -41,8 +58,8 @@ def main(database):
else:
for message in messages:
print(message)
- print('GoodBye!')
+ print('GoodBye!')
if __name__ == '__main__':
if len(sys.argv) < 2:
diff --git a/prompt_toolkit/layout/controls.py b/prompt_toolkit/layout/controls.py
index eca0c61e..b387f87b 100644
--- a/prompt_toolkit/layout/controls.py
+++ b/prompt_toolkit/layout/controls.py
@@ -423,7 +423,7 @@ class BufferControl(UIControl):
assert input_processors is None or isinstance(input_processors, list)
assert isinstance(include_default_input_processors, bool)
assert menu_position is None or callable(menu_position)
- assert lexer is None or isinstance(lexer, Lexer)
+ assert lexer is None or isinstance(lexer, Lexer), 'Got %r' % (lexer, )
assert (search_buffer_control is None or
callable(search_buffer_control) or
isinstance(search_buffer_control, SearchBufferControl))