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

141 lines, 72 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 read_init_file(self, s):
38 # type: (str) -> None
39 line_input.read_init_file(s)
40
41 def add_history(self, line):
42 # type: (str) -> None
43 line_input.add_history(line)
44
45 def read_history_file(self, path=None):
46 # type: (Optional[str]) -> None
47 line_input.read_history_file(path)
48
49 def write_history_file(self, path=None):
50 # type: (Optional[str]) -> None
51 line_input.write_history_file(path)
52
53 def set_completer(self, completer=None):
54 # type: (Optional[ReadlineCallback]) -> None
55 line_input.set_completer(completer)
56
57 def set_completer_delims(self, delims):
58 # type: (str) -> None
59 line_input.set_completer_delims(delims)
60
61 def set_completion_display_matches_hook(self, display=None):
62 # type: (Optional[_IDisplay]) -> None
63 hook = None
64 if display is not None:
65 hook = lambda *args: display.PrintCandidates(*args)
66
67 line_input.set_completion_display_matches_hook(hook)
68
69 def get_line_buffer(self):
70 # type: () -> str
71 return line_input.get_line_buffer()
72
73 def get_begidx(self):
74 # type: () -> int
75 return line_input.get_begidx()
76
77 def get_endidx(self):
78 # type: () -> int
79 return line_input.get_endidx()
80
81 def clear_history(self):
82 # type: () -> None
83 line_input.clear_history()
84
85 def get_history_item(self, pos):
86 # type: (int) -> str
87 return line_input.get_history_item(pos)
88
89 def remove_history_item(self, pos):
90 # type: (int) -> None
91 line_input.remove_history_item(pos)
92
93 def get_current_history_length(self):
94 # type: () -> int
95 return line_input.get_current_history_length()
96
97 def resize_terminal(self):
98 # type: () -> None
99 line_input.resize_terminal()
100
101 def list_funmap_names(self):
102 # type: () -> None
103 line_input.list_funmap_names()
104
105 def function_dumper(self, print_readably):
106 # type: (bool) -> None
107 line_input.function_dumper(print_readably)
108
109 def macro_dumper(self, print_readably):
110 # type: (bool) -> None
111 line_input.macro_dumper(print_readably)
112
113 def variable_dumper(self, print_readably):
114 # type: (bool) -> None
115 line_input.variable_dumper(print_readably)
116
117 def query_bindings(self, fn_name):
118 # type: (str) -> None
119 line_input.query_bindings(fn_name)
120
121
122def MaybeGetReadline():
123 # type: () -> Optional[Readline]
124 """Returns a readline "module" if we were built with readline support."""
125 if line_input is not None:
126 return Readline()
127
128 return None
129
130
131if __name__ == '__main__':
132 import sys
133 readline = MaybeGetReadline()
134 try:
135 prompt_str = sys.argv[1]
136 except IndexError:
137 prompt_str = '! '
138
139 while True:
140 x = readline.prompt_input(prompt_str)
141 print(x)