1010from argparse import ArgumentParser
1111from code import InteractiveConsole
1212from textwrap import dedent
13+ from _colorize import get_theme , theme_no_color
1314
1415
15- def execute (c , sql , suppress_errors = True ):
16+ def execute (c , sql , suppress_errors = True , theme = theme_no_color ):
1617 """Helper that wraps execution of SQL code.
1718
1819 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):
2526 for row in c .execute (sql ):
2627 print (row )
2728 except sqlite3 .Error as e :
29+ t = theme .traceback
2830 tp = type (e ).__name__
2931 try :
30- print ( f" { tp } ({ e .sqlite_errorname } ): { e } " , file = sys . stderr )
32+ tp += f" ({ e .sqlite_errorname } )"
3133 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+ )
3338 if not suppress_errors :
3439 sys .exit (1 )
3540
3641
3742class SqliteInteractiveConsole (InteractiveConsole ):
3843 """A simple SQLite REPL."""
3944
40- def __init__ (self , connection ):
45+ def __init__ (self , connection , use_color = False ):
4146 super ().__init__ ()
4247 self ._con = connection
4348 self ._cur = connection .cursor ()
49+ self ._use_color = use_color
4450
4551 def runsource (self , source , filename = "<input>" , symbol = "single" ):
4652 """Override runsource, the core of the InteractiveConsole REPL.
4753
4854 Return True if more input is needed; buffering is done automatically.
4955 Return False if input is a complete statement ready for execution.
5056 """
57+ theme = get_theme (force_no_color = not self ._use_color )
58+
5159 if not source or source .isspace ():
5260 return False
5361 if source [0 ] == "." :
@@ -61,12 +69,13 @@ def runsource(self, source, filename="<input>", symbol="single"):
6169 case "" :
6270 pass
6371 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 } ' )
6675 else :
6776 if not sqlite3 .complete_statement (source ):
6877 return True
69- execute (self ._cur , source )
78+ execute (self ._cur , source , theme = theme )
7079 return False
7180
7281
@@ -113,17 +122,21 @@ def main(*args):
113122 Each command will be run using execute() on the cursor.
114123 Type ".help" for more information; type ".quit" or { eofkey } to quit.
115124 """ ).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 } "
118131
119132 con = sqlite3 .connect (args .filename , isolation_level = None )
120133 try :
121134 if args .sql :
122135 # 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 )
124137 else :
125138 # No SQL provided; start the REPL.
126- console = SqliteInteractiveConsole (con )
139+ console = SqliteInteractiveConsole (con , use_color = True )
127140 try :
128141 import readline # noqa: F401
129142 except ImportError :
0 commit comments