OILS / frontend / py_readline.py View on Github | oilshell.org

117 lines, 60 significant
1"""
2py_readline.py: GNU readline wrapper that's also implemented in C++
3"""
4
5try:
6 import line_input
7except ImportError:
8 line_input = None
9
10from typing import Optional, TYPE_CHECKING
11if TYPE_CHECKING:
12 from core.completion import ReadlineCallback
13 from core.comp_ui import _IDisplay
14
15
16class Readline(object):
17 """A thin wrapper around GNU readline to make it usable from C++."""
18
19 def __init__(self):
20 # type: () -> None
21 assert line_input is not None
22
23 def prompt_input(self, prompt):
24 # type: (str) -> str
25 """
26 Print prompt, read line, and return it with trailing newline. Or raise
27 EOFError.
28 """
29 # Add trailing newline to make GNU readline conform to Python's
30 # f.readline() interface
31 return raw_input(prompt) + '\n'
32
33 def parse_and_bind(self, s):
34 # type: (str) -> None
35 line_input.parse_and_bind(s)
36
37 def add_history(self, line):
38 # type: (str) -> None
39 line_input.add_history(line)
40
41 def read_history_file(self, path=None):
42 # type: (Optional[str]) -> None
43 line_input.read_history_file(path)
44
45 def write_history_file(self, path=None):
46 # type: (Optional[str]) -> None
47 line_input.write_history_file(path)
48
49 def set_completer(self, completer=None):
50 # type: (Optional[ReadlineCallback]) -> None
51 line_input.set_completer(completer)
52
53 def set_completer_delims(self, delims):
54 # type: (str) -> None
55 line_input.set_completer_delims(delims)
56
57 def set_completion_display_matches_hook(self, display=None):
58 # type: (Optional[_IDisplay]) -> None
59 hook = None
60 if display is not None:
61 hook = lambda *args: display.PrintCandidates(*args)
62
63 line_input.set_completion_display_matches_hook(hook)
64
65 def get_line_buffer(self):
66 # type: () -> str
67 return line_input.get_line_buffer()
68
69 def get_begidx(self):
70 # type: () -> int
71 return line_input.get_begidx()
72
73 def get_endidx(self):
74 # type: () -> int
75 return line_input.get_endidx()
76
77 def clear_history(self):
78 # type: () -> None
79 line_input.clear_history()
80
81 def get_history_item(self, pos):
82 # type: (int) -> str
83 return line_input.get_history_item(pos)
84
85 def remove_history_item(self, pos):
86 # type: (int) -> None
87 line_input.remove_history_item(pos)
88
89 def get_current_history_length(self):
90 # type: () -> int
91 return line_input.get_current_history_length()
92
93 def resize_terminal(self):
94 # type: () -> None
95 line_input.resize_terminal()
96
97
98def MaybeGetReadline():
99 # type: () -> Optional[Readline]
100 """Returns a readline "module" if we were built with readline support."""
101 if line_input is not None:
102 return Readline()
103
104 return None
105
106
107if __name__ == '__main__':
108 import sys
109 readline = MaybeGetReadline()
110 try:
111 prompt_str = sys.argv[1]
112 except IndexError:
113 prompt_str = '! '
114
115 while True:
116 x = readline.prompt_input(prompt_str)
117 print(x)