1010from argparse import ArgumentParser
1111from code import InteractiveConsole
1212from textwrap import dedent
13+ from _colorize import get_theme , theme_no_color
1314
1415from ._completer import enable_completer
1516
1617
17- def execute (c , sql , suppress_errors = True ):
18+ def execute (c , sql , suppress_errors = True , theme = theme_no_color ):
1819 """Helper that wraps execution of SQL code.
1920
2021 This is used both by the REPL and by direct execution from the CLI.
@@ -27,41 +28,56 @@ def execute(c, sql, suppress_errors=True):
2728 for row in c .execute (sql ):
2829 print (row )
2930 except sqlite3 .Error as e :
31+ t = theme .traceback
3032 tp = type (e ).__name__
3133 try :
32- print ( f" { tp } ({ e .sqlite_errorname } ): { e } " , file = sys . stderr )
34+ tp += f" ({ e .sqlite_errorname } )"
3335 except AttributeError :
34- print (f"{ tp } : { e } " , file = sys .stderr )
36+ pass
37+ print (
38+ f"{ t .type } { tp } { t .reset } : { t .message } { e } { t .reset } " , file = sys .stderr
39+ )
3540 if not suppress_errors :
3641 sys .exit (1 )
3742
3843
3944class SqliteInteractiveConsole (InteractiveConsole ):
4045 """A simple SQLite REPL."""
4146
42- def __init__ (self , connection ):
47+ def __init__ (self , connection , use_color = False ):
4348 super ().__init__ ()
4449 self ._con = connection
4550 self ._cur = connection .cursor ()
51+ self ._use_color = use_color
4652
4753 def runsource (self , source , filename = "<input>" , symbol = "single" ):
4854 """Override runsource, the core of the InteractiveConsole REPL.
4955
5056 Return True if more input is needed; buffering is done automatically.
5157 Return False if input is a complete statement ready for execution.
5258 """
53- match source :
54- case ".version" :
55- print (f"{ sqlite3 .sqlite_version } " )
56- case ".help" :
57- print ("Enter SQL code and press enter." )
58- case ".quit" :
59- sys .exit (0 )
60- case _:
61- if not sqlite3 .complete_statement (source ):
62- return True
63- execute (self ._cur , source )
64- return False
59+ theme = get_theme (force_no_color = not self ._use_color )
60+
61+ if not source or source .isspace ():
62+ return False
63+ if source [0 ] == "." :
64+ match source [1 :].strip ():
65+ case "version" :
66+ print (f"{ sqlite3 .sqlite_version } " )
67+ case "help" :
68+ print ("Enter SQL code and press enter." )
69+ case "quit" :
70+ sys .exit (0 )
71+ case "" :
72+ pass
73+ case _ as unknown :
74+ t = theme .traceback
75+ self .write (f'{ t .type } Error{ t .reset } :{ t .message } unknown'
76+ f'command or invalid arguments: "{ unknown } ".\n { t .reset } ' )
77+ else :
78+ if not sqlite3 .complete_statement (source ):
79+ return True
80+ execute (self ._cur , source , theme = theme )
6581
6682
6783def main (* args ):
@@ -107,18 +123,22 @@ def main(*args):
107123 Each command will be run using execute() on the cursor.
108124 Type ".help" for more information; type ".quit" or { eofkey } to quit.
109125 """ ).strip ()
110- sys .ps1 = "sqlite> "
111- sys .ps2 = " ... "
126+
127+ theme = get_theme ()
128+ s = theme .syntax
129+
130+ sys .ps1 = f"{ s .prompt } sqlite> { s .reset } "
131+ sys .ps2 = f"{ s .prompt } ... { s .reset } "
112132
113133 con = sqlite3 .connect (args .filename , isolation_level = None )
114134 try :
115135 if args .sql :
116136 # SQL statement provided on the command-line; execute it directly.
117- execute (con , args .sql , suppress_errors = False )
137+ execute (con , args .sql , suppress_errors = False , theme = theme )
118138 else :
119139 # No SQL provided; start the REPL.
120140 with enable_completer ():
121- console = SqliteInteractiveConsole (con )
141+ console = SqliteInteractiveConsole (con , use_color = True )
122142 console .interact (banner , exitmsg = "" )
123143 finally :
124144 con .close ()
0 commit comments