10
10
from argparse import ArgumentParser
11
11
from code import InteractiveConsole
12
12
from textwrap import dedent
13
+ from _colorize import get_theme , theme_no_color
13
14
14
15
15
- def execute (c , sql , suppress_errors = True ):
16
+ def execute (c , sql , suppress_errors = True , theme = theme_no_color ):
16
17
"""Helper that wraps execution of SQL code.
17
18
18
19
This is used both by the REPL and by direct execution from the CLI.
@@ -25,29 +26,36 @@ def execute(c, sql, suppress_errors=True):
25
26
for row in c .execute (sql ):
26
27
print (row )
27
28
except sqlite3 .Error as e :
29
+ t = theme .traceback
28
30
tp = type (e ).__name__
29
31
try :
30
- print ( f" { tp } ({ e .sqlite_errorname } ): { e } " , file = sys . stderr )
32
+ tp += f" ({ e .sqlite_errorname } )"
31
33
except AttributeError :
32
- print (f"{ tp } : { e } " , file = sys .stderr )
34
+ pass
35
+ print (
36
+ f"{ t .type } { tp } { t .reset } : { t .message } { e } { t .reset } " , file = sys .stderr
37
+ )
33
38
if not suppress_errors :
34
39
sys .exit (1 )
35
40
36
41
37
42
class SqliteInteractiveConsole (InteractiveConsole ):
38
43
"""A simple SQLite REPL."""
39
44
40
- def __init__ (self , connection ):
45
+ def __init__ (self , connection , use_color = False ):
41
46
super ().__init__ ()
42
47
self ._con = connection
43
48
self ._cur = connection .cursor ()
49
+ self ._use_color = use_color
44
50
45
51
def runsource (self , source , filename = "<input>" , symbol = "single" ):
46
52
"""Override runsource, the core of the InteractiveConsole REPL.
47
53
48
54
Return True if more input is needed; buffering is done automatically.
49
55
Return False if input is a complete statement ready for execution.
50
56
"""
57
+ theme = get_theme (force_no_color = not self ._use_color )
58
+
51
59
if not source or source .isspace ():
52
60
return False
53
61
if source [0 ] == "." :
@@ -61,12 +69,13 @@ def runsource(self, source, filename="<input>", symbol="single"):
61
69
case "" :
62
70
pass
63
71
case _ as unknown :
64
- self .write ("Error: unknown command or invalid arguments:"
65
- f' "{ unknown } ".\n ' )
72
+ t = theme .traceback
73
+ self .write (f'{ t .type } Error{ t .reset } :{ t .message } unknown'
74
+ f'command or invalid arguments: "{ unknown } ".\n { t .reset } ' )
66
75
else :
67
76
if not sqlite3 .complete_statement (source ):
68
77
return True
69
- execute (self ._cur , source )
78
+ execute (self ._cur , source , theme = theme )
70
79
return False
71
80
72
81
@@ -113,17 +122,21 @@ def main(*args):
113
122
Each command will be run using execute() on the cursor.
114
123
Type ".help" for more information; type ".quit" or { eofkey } to quit.
115
124
""" ).strip ()
116
- sys .ps1 = "sqlite> "
117
- sys .ps2 = " ... "
125
+
126
+ theme = get_theme ()
127
+ s = theme .syntax
128
+
129
+ sys .ps1 = f"{ s .prompt } sqlite> { s .reset } "
130
+ sys .ps2 = f"{ s .prompt } ... { s .reset } "
118
131
119
132
con = sqlite3 .connect (args .filename , isolation_level = None )
120
133
try :
121
134
if args .sql :
122
135
# SQL statement provided on the command-line; execute it directly.
123
- execute (con , args .sql , suppress_errors = False )
136
+ execute (con , args .sql , suppress_errors = False , theme = theme )
124
137
else :
125
138
# No SQL provided; start the REPL.
126
- console = SqliteInteractiveConsole (con )
139
+ console = SqliteInteractiveConsole (con , use_color = True )
127
140
try :
128
141
import readline # noqa: F401
129
142
except ImportError :
0 commit comments