11# -*- coding: utf-8 -*-
22#
3- # Copyright (C) 2009-2010, 2013-2015, 2017, 2023 Rocky Bernstein
3+ # Copyright (C) 2009-2010, 2013-2015, 2017, 2023-2024 Rocky Bernstein
44# <rocky@gnu.org>
55#
66# This program is free software: you can redistribute it and/or modify
2020import io
2121import sys
2222
23- from trepan import misc as Mmisc
2423from trepan .inout import base as Mbase
2524
26-
27- def readline_importable () -> bool :
28- try :
29- import readline # NOQA
30-
31- return True
32- except ImportError :
33- return False
34- return # Not reached
35-
25+ try :
26+ from prompt_toolkit import PromptSession , HTML
27+ from prompt_toolkit .styles import Style
28+ from prompt_toolkit .history import FileHistory
29+ except :
30+ PromptSession = lambda history : None
31+ FileHistory = lambda history : None
32+ HTML = lambda string : string
3633
3734class DebuggerUserInput (Mbase .DebuggerInputBase ):
3835 """Debugger input connected to what we think of as a end-user input
3936 as opposed to a relay mechanism to another process. Input could be
4037 interactive terminal, but it might be file input."""
4138
4239 def __init__ (self , inp = None , opts = None ):
43- self .input = inp or sys .stdin
44- self .line_edit = None # Our name for GNU readline capability
45- self .open (self .input , opts )
40+
41+ if opts and opts .get ("readline" ) == "prompt_toolkit" :
42+ self .session = PromptSession (history = FileHistory (opts .get ("histfile" )))
43+ self .input = self .session .input
44+ self .session .enable_history_search = True
45+ self .line_edit = True
46+ self .closed = False
47+ self .use_raw = False
48+ else :
49+ self .session = None
50+ self .input = inp or sys .stdin
51+ self .line_edit = None # Our name for GNU readline capability
52+ self .open (self .input , opts )
53+
4654 return
4755
4856 def close (self ):
4957 self .input .close ()
5058 self .closed = True
5159 return
5260
53- DEFAULT_OPEN_READ_OPTS = {
54- "use_raw" : True ,
55- "try_readline" : True ,
56- }
57-
5861 def use_history (self ):
59- return self .use_raw and readline_importable ()
62+ return self .use_raw
6063
6164 def open (self , inp , opts = {}):
6265 """Use this to set where to read from.
6366
64- Set opts['try_lineedit'] if you want this input to interact
65- with GNU-like readline library. By default, we will assume to
66- try importing and using readline. If readline is not
67- importable, line editing is not available whether or not
68- opts['try_readline'] is set.
69-
7067 Set opts['use_raw'] if input should use Python's use_raw(). If
7168 however 'inp' is a string and opts['use_raw'] is not set, we
7269 will assume no raw output. Note that an individual readline
7370 may override the setting.
7471 """
75- get_option = lambda key : Mmisc .option_set (
76- opts , key , self .DEFAULT_OPEN_READ_OPTS
77- )
7872 if (
7973 isinstance (inp , io .TextIOWrapper )
8074 or isinstance (inp , io .StringIO )
8175 or hasattr (inp , "isatty" )
8276 and inp .isatty ()
8377 ):
84- self .use_raw = get_option ("use_raw" )
78+ self .use_raw = opts and opts . get ("use_raw" , False )
8579 elif isinstance (inp , "string" .__class__ ): # FIXME
8680 if opts is None :
8781 self .use_raw = False
8882 else :
89- self .use_raw = get_option ("use_raw" )
83+ self .use_raw = opts . get ("use_raw" , False )
9084 pass
9185 inp = open (inp , "r" )
9286 else :
9387 raise IOError ("Invalid input type (%s) for %s" % (type (inp ), inp ))
9488 self .input = inp
95- self .line_edit = get_option ("try_readline" ) and readline_importable ()
89+ self .line_edit = bool (opts and opts .get ("readline" ))
90+
9691 self .closed = False
9792 return
9893
@@ -107,6 +102,12 @@ def readline(self, use_raw=None, prompt=""):
107102 initialization is used.
108103 """
109104 # FIXME we don't do command completion.
105+ if self .session :
106+ # Using prompt_toolkit
107+ html_prompt = HTML (f"<u>{ prompt .strip ()} </u> " )
108+ line = self .session .prompt (html_prompt , style = Style .from_dict ({"" : "" }))
109+ return line .rstrip ("\n " )
110+
110111 if use_raw is None :
111112 use_raw = self .use_raw
112113 pass
@@ -131,7 +132,6 @@ def readline(self, use_raw=None, prompt=""):
131132
132133# Demo
133134if __name__ == "__main__" :
134- print ("readline importable: " , readline_importable ())
135135 inp = DebuggerUserInput (__file__ )
136136 line = inp .readline ()
137137 print (line )
0 commit comments