A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ipython_view.py
Go to the documentation of this file.
1"""
2Backend to the console plugin.
3
4@author: Eitan Isaacson
5@organization: IBM Corporation
6@copyright: Copyright (c) 2007 IBM Corporation
7@license: BSD
8
9All rights reserved. This program and the accompanying materials are made
10available under the terms of the BSD which accompanies this distribution, and
11is available at U{http://www.opensource.org/licenses/bsd-license.php}
12"""
13
14# this file is a modified version of source code from the Accerciser project
15# https://wiki.gnome.org/Apps/Accerciser
16
17import gi
18
19gi.require_version("Gtk", "3.0")
20import os
21import re
22import sys
23from functools import reduce
24from io import StringIO
25
26from gi.repository import Gdk, GLib, Gtk, Pango
27from pkg_resources import parse_version
28
29## Try to import IPython
30try:
31 import IPython
32except ImportError:
33 ##@ var IPython
34 #
35 IPython = None
36
37
38## IterableIPShell class
40 ## @var IP
41 # IP
42 ## @var iter_more
43 # iterate more
44 ## @var history_level
45 # history level
46 ## @var complete_sep
47 # separators
48 ## @var no_input_splitter
49 # no input splitter
50 ## @var lines
51 # lines
52 ## @var indent_spaces
53 # indent spaces
54 ## @var prompt
55 # prompt
56 ## @var header
57 # header
58 ## @var config
59 # config
60 ## @var colors
61 # colors
62 ## @var raw_input
63 # raw input
64
66 self,
67 argv=[],
68 user_ns=None,
69 user_global_ns=None,
70 cin=None,
71 cout=None,
72 cerr=None,
73 input_func=None,
74 ):
75 """!
76 Constructor for the IterableIPShell class
77 @param self: this object
78 @param argv: Command line options for IPython
79 @param user_ns: User namespace.
80 @param user_global_ns: User global namespace.
81 @param cin: Console standard input.
82 @param cout: Console standard output.
83 @param cerr: Console standard error.
84 @param input_func: Replacement for builtin raw_input()
85 """
86 io = IPython.utils.io
87 if input_func:
88 IPython.terminal.interactiveshell.raw_input_original = input_func
89 if IPython.version_info < (8,):
90 if cin:
91 io.stdin = io.IOStream(cin)
92 if cout:
93 io.stdout = io.IOStream(cout)
94 if cerr:
95 io.stderr = io.IOStream(cerr)
96 else:
97 if cin:
98 sys.stdin = cin
99 if cout:
100 sys.stdout = cout
101 if cerr:
102 sys.stderr = cerr
103
104 # This is to get rid of the blockage that occurs during
105 # IPython.Shell.InteractiveShell.user_setup()
106 io.raw_input = lambda x: None
107
108 os.environ["TERM"] = "dumb"
109 excepthook = sys.excepthook
110
111 from traitlets.config.loader import Config
112
113 cfg = Config()
114 cfg.InteractiveShell.colors = "Linux"
115 cfg.Completer.use_jedi = False
116
117 if IPython.version_info < (8,):
118 # InteractiveShell's __init__ overwrites io.stdout,io.stderr with
119 # sys.stdout, sys.stderr, this makes sure they are right
120 old_stdout, old_stderr = sys.stdout, sys.stderr
121 sys.stdout, sys.stderr = io.stdout.stream, io.stderr.stream
122
123 # InteractiveShell inherits from SingletonConfigurable, so use instance()
124 #
125 self.IP = IPython.terminal.embed.InteractiveShellEmbed.instance(config=cfg, user_ns=user_ns)
126
127 if IPython.version_info < (8,):
128 sys.stdout, sys.stderr = old_stdout, old_stderr
129
130 self.IP.system = lambda cmd: self.shell(
131 self.IP.var_expand(cmd), header="IPython system call: "
132 )
133 # local_ns=user_ns)
134 # global_ns=user_global_ns)
135 # verbose=self.IP.rc.system_verbose)
136
137 self.IP.raw_input = input_func
138 sys.excepthook = excepthook
139 self.iter_more = 0
141 self.complete_sep = re.compile("[\s\{\}\[\]\‍(\‍)]")
142 self.updateNamespace({"exit": lambda: None})
143 self.updateNamespace({"quit": lambda: None})
144 # Workaround for updating namespace with sys.modules
145 #
146 self.__update_namespace()
147
148 # Avoid using input splitter when not really needed.
149 # Perhaps it could work even before 5.8.0
150 # But it definitely does not work any more with >= 7.0.0
151 self.no_input_splitter = parse_version(IPython.release.version) >= parse_version("5.8.0")
152 self.lines = []
154
156 """!
157 Update self.IP namespace for autocompletion with sys.modules
158 @return none
159 """
160 for k, v in list(sys.modules.items()):
161 if not "." in k:
162 self.IP.user_ns.update({k: v})
163
164 def execute(self):
165 """!
166 Executes the current line provided by the shell object.
167 @return none
168 """
169 self.history_level = 0
170
171 if IPython.version_info < (8,):
172 # this is needed because some functions in IPython use 'print' to print
173 # output (like 'who')
174
175 orig_stdout = sys.stdout
176 sys.stdout = IPython.utils.io.stdout
177
178 orig_stdin = sys.stdin
179 sys.stdin = IPython.utils.io.stdin
180
182
183 self.IP.hooks.pre_prompt_hook()
184 if self.iter_more:
185 try:
186 self.prompt = self.generatePrompt(True)
187 except:
188 self.IP.showtraceback()
189 if self.IP.autoindent:
190 self.IP.rl_do_indent = True
191
192 try:
193 line = self.IP.raw_input(self.prompt)
194 except KeyboardInterrupt:
195 self.IP.write("\nKeyboardInterrupt\n")
196 if self.no_input_splitter:
197 self.lines = []
198 else:
199 self.IP.input_splitter.reset()
200 except:
201 self.IP.showtraceback()
202 else:
203 if self.no_input_splitter:
204 self.lines.append(line)
205 (status, self.indent_spaces) = self.IP.check_complete("\n".join(self.lines))
206 self.iter_more = status == "incomplete"
207 else:
208 self.IP.input_splitter.push(line)
209 self.iter_more = self.IP.input_splitter.push_accepts_more()
210 if not self.iter_more:
211 if self.no_input_splitter:
212 source_raw = "\n".join(self.lines)
213 self.lines = []
214 else:
215 source_raw = self.IP.input_splitter.raw_reset()
216 self.IP.run_cell(source_raw, store_history=True)
217 self.IP.rl_do_indent = False
218 else:
219 # TODO: Auto-indent
220 #
221 self.IP.rl_do_indent = True
222 pass
223 self.prompt = self.generatePrompt(self.iter_more)
224
225 if IPython.version_info < (8,):
226 sys.stdout = orig_stdout
227 sys.stdin = orig_stdin
228
229 def generatePrompt(self, is_continuation):
230 """!
231 Generate prompt depending on is_continuation value
232
233 @param is_continuation
234 @return: The prompt string representation
235
236 """
237
238 if is_continuation:
239 prompt = "... "
240 else:
241 prompt = ">>> "
242 return prompt
243
244 def historyBack(self):
245 """!
246 Provides one history command back.
247
248 @param self this object
249 @return: The command string.
250 """
251 self.history_level -= 1
252 if not self._getHistory():
253 self.history_level += 1
254 return self._getHistory()
255
256 def historyForward(self):
257 """!
258 Provides one history command forward.
259
260 @param self this object
261 @return: The command string.
262 """
263 if self.history_level < 0:
264 self.history_level += 1
265 return self._getHistory()
266
267 def _getHistory(self):
268 """!
269 Gets the command string of the current history level.
270
271 @param self this object
272 @return: Historic command string.
273 """
274 try:
275 rv = self.IP.user_ns["In"][self.history_level].strip("\n")
276 except IndexError:
277 rv = ""
278 return rv
279
280 def updateNamespace(self, ns_dict):
281 """!
282 Add the current dictionary to the shell namespace.
283
284 @param ns_dict: A dictionary of symbol-values.
285 @return none
286 """
287 self.IP.user_ns.update(ns_dict)
288
289 def complete(self, line):
290 """!
291 Returns an auto completed line and/or possibilities for completion.
292
293 @param line: Given line so far.
294 @return: Line completed as for as possible, and possible further completions.
295 """
296 split_line = self.complete_sep.split(line)
297 if split_line[-1]:
298 possibilities = self.IP.complete(split_line[-1])
299 else:
300 completed = line
301 possibilities = ["", []]
302 if possibilities:
303
304 def _commonPrefix(str1, str2):
305 """!
306 Reduction function. returns common prefix of two given strings.
307
308 @param str1: First string.
309 @param str2: Second string
310 @return: Common prefix to both strings.
311 """
312 for i in range(len(str1)):
313 if not str2.startswith(str1[: i + 1]):
314 return str1[:i]
315 return str1
316
317 if possibilities[1]:
318 common_prefix = reduce(_commonPrefix, possibilities[1]) or split_line[-1]
319 completed = line[: -len(split_line[-1])] + common_prefix
320 else:
321 completed = line
322 else:
323 completed = line
324 return completed, possibilities[1]
325
326 def shell(self, cmd, verbose=0, debug=0, header=""):
327 """!
328 Replacement method to allow shell commands without them blocking.
329
330 @param cmd: Shell command to execute.
331 @param verbose: Verbosity
332 @param debug: Debug level
333 @param header: Header to be printed before output
334 @return none
335 """
336 stat = 0
337 if verbose or debug:
338 print(header + cmd)
339 # flush stdout so we don't mangle python's buffering
340 if not debug:
341 input, output = os.popen4(cmd)
342 print(output.read())
343 output.close()
344 input.close()
345
346
347## ConsoleView class
348class ConsoleView(Gtk.TextView):
349 ## @var ANSI_COLORS
350 # color list
351 ## @var text_buffer
352 # text buffer
353 ## @var mark
354 # scroll mark
355 ## @var color_pat
356 # color pattern
357 ## @var line_start
358 # line start
359 ## @var onKeyPress
360 # onKeyPress function
361 ## @var _write
362 # _write function
363 ## @var _showPrompt
364 # _showPrompt function
365 ## @var _changeLine
366 # _changeLine function
367 ## @var _showReturned
368 # _showReturned function
369 ## @var prompt
370 # prompt function
371 ## @var no_input_splitter
372 # no input splitter
373
374 """
375 Specialized text view for console-like workflow.
376
377 @cvar ANSI_COLORS: Mapping of terminal control sequence values to
378 tuples containing foreground and background color names.
379 @type ANSI_COLORS: dictionary
380
381 @ivar text_buffer: Widget's text buffer.
382 @type text_buffer: Gtk.TextBuffer
383 @ivar color_pat: Regex of terminal color pattern
384 @type color_pat: _sre.SRE_Pattern
385 @ivar mark: Scroll mark for automatic scrolling on input.
386 @type mark: Gtk.TextMark
387 @ivar line_start: Start of command line mark.
388 @type line_start: Gtk.TextMark
389 """
390 ANSI_COLORS = {
391 "0;30": ("Black", None),
392 "0;31": ("Red", None),
393 "0;32": ("Green", None),
394 "0;33": ("Brown", None),
395 "0;34": ("Blue", None),
396 "0;35": ("Purple", None),
397 "0;36": ("Cyan", None),
398 "0;37": ("LightGray", None),
399 "1;30": ("DarkGray", None),
400 "1;31": ("DarkRed", None),
401 "1;32": ("SeaGreen", None),
402 "1;33": ("Yellow", None),
403 "1;34": ("LightBlue", None),
404 "1;35": ("MediumPurple", None),
405 "1;36": ("LightCyan", None),
406 "1;37": ("White", None),
407 "38;5;124;43": ("DarkRed", "Yellow"),
408 "38;5;241": ("Gray", None),
409 "38;5;241;43": ("Gray", "Yellow"),
410 "39": ("Black", None),
411 "39;49": ("Red", "White"),
412 "43": (None, "Yellow"),
413 "49": (None, "White"),
414 }
415
416 def __init__(self):
417 """
418 Initialize console view.
419 """
420 Gtk.TextView.__init__(self)
421 self.modify_font(Pango.FontDescription("Mono"))
422 self.set_cursor_visible(True)
423 self.text_buffer = self.get_buffer()
424 self.mark = self.text_buffer.create_mark(
425 "scroll_mark", self.text_buffer.get_end_iter(), False
426 )
427 for code in self.ANSI_COLORS:
428 self.text_buffer.create_tag(
429 code,
430 foreground=self.ANSI_COLORS[code][0],
431 background=self.ANSI_COLORS[code][1],
432 weight=700,
433 )
434 self.text_buffer.create_tag("0")
435 self.text_buffer.create_tag("notouch", editable=False)
436 self.color_pat = re.compile("\x01?\x1b\[(.*?)m\x02?")
437 self.line_start = self.text_buffer.create_mark(
438 "line_start", self.text_buffer.get_end_iter(), True
439 )
440 self.connect("key-press-event", self.onKeyPressonKeyPress)
441
442 def write(self, text, editable=False):
443 """!
444 Write given text to buffer.
445
446 @param text: Text to append.
447 @param editable: If true, added text is editable.
448 @return none
449 """
450 GLib.idle_add(self._write_write, text, editable)
451
452 def _write(self, text, editable=False):
453 """!
454 Write given text to buffer.
455
456 @param text: Text to append.
457 @param editable: If true, added text is editable.
458 @return none
459 """
460 segments = self.color_pat.split(text)
461 segment = segments.pop(0)
462 start_mark = self.text_buffer.create_mark(None, self.text_buffer.get_end_iter(), True)
463 self.text_buffer.insert(self.text_buffer.get_end_iter(), segment)
464
465 if segments:
466 ansi_tags = self.color_pat.findall(text)
467 for tag in ansi_tags:
468 i = segments.index(tag)
469 self.text_buffer.insert_with_tags_by_name(
470 self.text_buffer.get_end_iter(), segments[i + 1], str(tag)
471 )
472 segments.pop(i)
473 if not editable:
474 self.text_buffer.apply_tag_by_name(
475 "notouch",
476 self.text_buffer.get_iter_at_mark(start_mark),
477 self.text_buffer.get_end_iter(),
478 )
479 self.text_buffer.delete_mark(start_mark)
480 self.scroll_mark_onscreen(self.mark)
481
482 def showPrompt(self, prompt):
483 """!
484 Prints prompt at start of line.
485
486 @param prompt: Prompt to print.
487 @return none
488 """
489 GLib.idle_add(self._showPrompt_showPrompt, prompt)
490
491 def _showPrompt(self, prompt):
492 """!
493 Prints prompt at start of line.
494
495 @param prompt: Prompt to print.
496 @return none
497 """
498 self._write_write(prompt)
499 self.text_buffer.move_mark(self.line_start, self.text_buffer.get_end_iter())
500
501 def changeLine(self, text):
502 """!
503 Replace currently entered command line with given text.
504
505 @param text: Text to use as replacement.
506 @return none
507 """
508 GLib.idle_add(self._changeLine_changeLine, text)
509
510 def _changeLine(self, text):
511 """!
512 Replace currently entered command line with given text.
513
514 @param text: Text to use as replacement.
515 @return none
516 """
517 iter = self.text_buffer.get_iter_at_mark(self.line_start)
518 iter.forward_to_line_end()
519 self.text_buffer.delete(self.text_buffer.get_iter_at_mark(self.line_start), iter)
520 self._write_write(text, True)
521
522 def getCurrentLine(self):
523 """!
524 Get text in current command line.
525
526 @return Text of current command line.
527 """
528 rv = self.text_buffer.get_slice(
529 self.text_buffer.get_iter_at_mark(self.line_start),
530 self.text_buffer.get_end_iter(),
531 False,
532 )
533 return rv
534
535 def showReturned(self, text):
536 """!
537 Show returned text from last command and print new prompt.
538
539 @param text: Text to show.
540 @return none
541 """
542 GLib.idle_add(self._showReturned_showReturned, text)
543
544 def _showReturned(self, text):
545 """!
546 Show returned text from last command and print new prompt.
547
548 @param text: Text to show.
549 @return none
550 """
551 iter = self.text_buffer.get_iter_at_mark(self.line_start)
552 iter.forward_to_line_end()
553 self.text_buffer.apply_tag_by_name(
554 "notouch", self.text_buffer.get_iter_at_mark(self.line_start), iter
555 )
556 self._write_write("\n" + text)
557 if text:
558 self._write_write("\n")
560 self.text_buffer.move_mark(self.line_start, self.text_buffer.get_end_iter())
561 self.text_buffer.place_cursor(self.text_buffer.get_end_iter())
562
563 if self.IP.rl_do_indent:
565 indentation = self.indent_spaces
566 else:
567 indentation = self.IP.input_splitter.indent_spaces * " "
568 self.text_buffer.insert_at_cursor(indentation)
569
570 def onKeyPress(self, widget, event):
571 """!
572 Key press callback used for correcting behavior for console-like
573 interfaces. For example 'home' should go to prompt, not to beginning of
574 line.
575
576 @param widget: Widget that key press accored in.
577 @param event: Event object
578 @return Return True if event should not trickle.
579 """
580 insert_mark = self.text_buffer.get_insert()
581 insert_iter = self.text_buffer.get_iter_at_mark(insert_mark)
582 selection_mark = self.text_buffer.get_selection_bound()
583 selection_iter = self.text_buffer.get_iter_at_mark(selection_mark)
584 start_iter = self.text_buffer.get_iter_at_mark(self.line_start)
585 if event.keyval == Gdk.KEY_Home:
586 if (
587 event.state & Gdk.ModifierType.CONTROL_MASK
588 or event.state & Gdk.ModifierType.MOD1_MASK
589 ):
590 pass
591 elif event.state & Gdk.ModifierType.SHIFT_MASK:
592 self.text_buffer.move_mark(insert_mark, start_iter)
593 return True
594 else:
595 self.text_buffer.place_cursor(start_iter)
596 return True
597 elif event.keyval == Gdk.KEY_Left:
598 insert_iter.backward_cursor_position()
599 if not insert_iter.editable(True):
600 return True
601 elif event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval in [ord("L"), ord("l")]:
602 # clear previous output on Ctrl+L, but remember current input line + cursor position
603 cursor_offset = self.text_buffer.get_property("cursor-position")
604 cursor_pos_in_line = cursor_offset - start_iter.get_offset() + len(self.prompt)
605 current_input = self.text_buffer.get_text(
606 start_iter, self.text_buffer.get_end_iter(), False
607 )
608 self.text_buffer.set_text(self.prompt + current_input)
609 self.text_buffer.move_mark(
610 self.line_start, self.text_buffer.get_iter_at_offset(len(self.prompt))
611 )
612 self.text_buffer.place_cursor(self.text_buffer.get_iter_at_offset(cursor_pos_in_line))
613 return True
614 elif event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval in [Gdk.KEY_k, Gdk.KEY_K]:
615 # clear text after input cursor on Ctrl+K
616 if insert_iter.editable(True):
617 self.text_buffer.delete(insert_iter, self.text_buffer.get_end_iter())
618 return True
619 elif event.state & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.KEY_C:
620 # copy selection on Ctrl+C (upper-case 'C' only)
621 self.text_buffer.copy_clipboard(Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD))
622 return True
623 elif not event.string:
624 pass
625 elif start_iter.compare(insert_iter) <= 0 and start_iter.compare(selection_iter) <= 0:
626 pass
627 elif start_iter.compare(insert_iter) > 0 and start_iter.compare(selection_iter) > 0:
628 self.text_buffer.place_cursor(start_iter)
629 elif insert_iter.compare(selection_iter) < 0:
630 self.text_buffer.move_mark(insert_mark, start_iter)
631 elif insert_iter.compare(selection_iter) > 0:
632 self.text_buffer.move_mark(selection_mark, start_iter)
633
634 return self.onKeyPressExtend(event)
635
636 def onKeyPressExtend(self, event):
637 """!
638 For some reason we can't extend onKeyPress directly (bug #500900).
639 @param event key press
640 @return none
641 """
642 pass
643
644
645## IPythonView class
646class IPythonView(ConsoleView, IterableIPShell):
647 ## @var cout
648 # cout
649 ## @var interrupt
650 # interrupt
651 ## @var execute
652 # execute
653 ## @var prompt
654 # prompt
655 ## @var showPrompt
656 # show prompt
657 ## @var history_pos
658 # history list
659 ## @var window
660 # GTK Window
661 """
662 Sub-class of both modified IPython shell and L{ConsoleView} this makes
663 a GTK+ IPython console.
664 """
665
666 def __init__(self):
667 """
668 Initialize. Redirect I/O to console.
669 """
670 ConsoleView.__init__(self)
671 self.cout = StringIO()
672 IterableIPShell.__init__(self, cout=self.cout, cerr=self.cout, input_func=self.raw_input)
673 self.interrupt = False
674 self.execute()
676 self.cout.truncate(0)
678
679 def raw_input(self, prompt=""):
680 """!
681 Custom raw_input() replacement. Gets current line from console buffer.
682
683 @param prompt: Prompt to print. Here for compatibility as replacement.
684 @return The current command line text.
685 """
686 if self.interrupt:
687 self.interrupt = False
688 raise KeyboardInterrupt
689 return self.getCurrentLine()
690
691 def onKeyPressExtend(self, event):
692 """!
693 Key press callback with plenty of shell goodness, like history,
694 autocompletions, etc.
695
696 @param event: Event object.
697 @return True if event should not trickle.
698 """
699
700 if event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == 99:
701 self.interrupt = True
702 self._processLine()
703 return True
704 elif event.keyval == Gdk.KEY_Return:
705 self._processLine()
706 return True
707 elif event.keyval == Gdk.KEY_Up:
708 self.changeLine(self.historyBack())
709 return True
710 elif event.keyval == Gdk.KEY_Down:
711 self.changeLine(self.historyForward())
712 return True
713 elif event.keyval == Gdk.KEY_Tab:
714 if not self.getCurrentLine().strip():
715 return False
716 completed, possibilities = self.complete(self.getCurrentLine())
717 if len(possibilities) > 1:
718 slice = self.getCurrentLine()
719 self.write("\n")
720 for symbol in possibilities:
721 self.write(symbol + "\n")
723 self.changeLine(completed or slice)
724 return True
725
726 def _processLine(self):
727 """!
728 Process current command line.
729 @return none
730 """
731 self.history_pos = 0
732 self.execute()
733 rv = self.cout.getvalue()
734 if rv:
735 rv = rv.strip("\n")
736 self.showReturned(rv)
737 self.cout.truncate(0)
738 self.cout.seek(0)
739
740
741if __name__ == "__main__":
742 window = Gtk.Window()
743 window.set_default_size(640, 320)
744 window.connect("delete-event", lambda x, y: Gtk.main_quit())
745 window.add(IPythonView())
746 window.show_all()
747 Gtk.main()
write(self, text, editable=False)
Write given text to buffer.
getCurrentLine(self)
Get text in current command line.
onKeyPressExtend(self, event)
For some reason we can't extend onKeyPress directly (bug #500900).
_showPrompt(self, prompt)
Prints prompt at start of line.
_write(self, text, editable=False)
Write given text to buffer.
showReturned(self, text)
Show returned text from last command and print new prompt.
_changeLine(self, text)
Replace currently entered command line with given text.
showPrompt(self, prompt)
Prints prompt at start of line.
_showReturned(self, text)
Show returned text from last command and print new prompt.
changeLine(self, text)
Replace currently entered command line with given text.
onKeyPress(self, widget, event)
Key press callback used for correcting behavior for console-like interfaces.
_showReturned
_showReturned function
onKeyPressExtend(self, event)
Key press callback with plenty of shell goodness, like history, autocompletions, etc.
_processLine(self)
Process current command line.
raw_input(self, prompt="")
Custom raw_input() replacement.
historyBack(self)
Provides one history command back.
_getHistory(self)
Gets the command string of the current history level.
historyForward(self)
Provides one history command forward.
complete(self, line)
Returns an auto completed line and/or possibilities for completion.
updateNamespace(self, ns_dict)
Add the current dictionary to the shell namespace.
shell(self, cmd, verbose=0, debug=0, header="")
Replacement method to allow shell commands without them blocking.
__update_namespace(self)
Update self.IP namespace for autocompletion with sys.modules.
execute(self)
Executes the current line provided by the shell object.
__init__(self, argv=[], user_ns=None, user_global_ns=None, cin=None, cout=None, cerr=None, input_func=None)
Constructor for the IterableIPShell class.
generatePrompt(self, is_continuation)
Generate prompt depending on is_continuation value.
#define delete