annotate lldb/source/Host/common/Editline.cpp @ 173:0572611fdcc8 llvm10 llvm12

reorgnization done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 11:55:54 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===-- Editline.cpp ------------------------------------------------------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include <iomanip>
anatofuz
parents:
diff changeset
10 #include <iostream>
anatofuz
parents:
diff changeset
11 #include <limits.h>
anatofuz
parents:
diff changeset
12
anatofuz
parents:
diff changeset
13 #include "lldb/Host/ConnectionFileDescriptor.h"
anatofuz
parents:
diff changeset
14 #include "lldb/Host/Editline.h"
anatofuz
parents:
diff changeset
15 #include "lldb/Host/FileSystem.h"
anatofuz
parents:
diff changeset
16 #include "lldb/Host/Host.h"
anatofuz
parents:
diff changeset
17 #include "lldb/Utility/CompletionRequest.h"
anatofuz
parents:
diff changeset
18 #include "lldb/Utility/FileSpec.h"
anatofuz
parents:
diff changeset
19 #include "lldb/Utility/LLDBAssert.h"
anatofuz
parents:
diff changeset
20 #include "lldb/Utility/SelectHelper.h"
anatofuz
parents:
diff changeset
21 #include "lldb/Utility/Status.h"
anatofuz
parents:
diff changeset
22 #include "lldb/Utility/StreamString.h"
anatofuz
parents:
diff changeset
23 #include "lldb/Utility/StringList.h"
anatofuz
parents:
diff changeset
24 #include "lldb/Utility/Timeout.h"
anatofuz
parents:
diff changeset
25
anatofuz
parents:
diff changeset
26 #include "llvm/Support/FileSystem.h"
anatofuz
parents:
diff changeset
27 #include "llvm/Support/Threading.h"
anatofuz
parents:
diff changeset
28
anatofuz
parents:
diff changeset
29 using namespace lldb_private;
anatofuz
parents:
diff changeset
30 using namespace lldb_private::line_editor;
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 // Workaround for what looks like an OS X-specific issue, but other platforms
anatofuz
parents:
diff changeset
33 // may benefit from something similar if issues arise. The libedit library
anatofuz
parents:
diff changeset
34 // doesn't explicitly initialize the curses termcap library, which it gets away
anatofuz
parents:
diff changeset
35 // with until TERM is set to VT100 where it stumbles over an implementation
anatofuz
parents:
diff changeset
36 // assumption that may not exist on other platforms. The setupterm() function
anatofuz
parents:
diff changeset
37 // would normally require headers that don't work gracefully in this context,
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
38 // so the function declaration has been hoisted here.
150
anatofuz
parents:
diff changeset
39 #if defined(__APPLE__)
anatofuz
parents:
diff changeset
40 extern "C" {
anatofuz
parents:
diff changeset
41 int setupterm(char *term, int fildes, int *errret);
anatofuz
parents:
diff changeset
42 }
anatofuz
parents:
diff changeset
43 #define USE_SETUPTERM_WORKAROUND
anatofuz
parents:
diff changeset
44 #endif
anatofuz
parents:
diff changeset
45
anatofuz
parents:
diff changeset
46 // Editline uses careful cursor management to achieve the illusion of editing a
anatofuz
parents:
diff changeset
47 // multi-line block of text with a single line editor. Preserving this
anatofuz
parents:
diff changeset
48 // illusion requires fairly careful management of cursor state. Read and
anatofuz
parents:
diff changeset
49 // understand the relationship between DisplayInput(), MoveCursor(),
anatofuz
parents:
diff changeset
50 // SetCurrentLine(), and SaveEditedLine() before making changes.
anatofuz
parents:
diff changeset
51
anatofuz
parents:
diff changeset
52 #define ESCAPE "\x1b"
anatofuz
parents:
diff changeset
53 #define ANSI_FAINT ESCAPE "[2m"
anatofuz
parents:
diff changeset
54 #define ANSI_UNFAINT ESCAPE "[22m"
anatofuz
parents:
diff changeset
55 #define ANSI_CLEAR_BELOW ESCAPE "[J"
anatofuz
parents:
diff changeset
56 #define ANSI_CLEAR_RIGHT ESCAPE "[K"
anatofuz
parents:
diff changeset
57 #define ANSI_SET_COLUMN_N ESCAPE "[%dG"
anatofuz
parents:
diff changeset
58 #define ANSI_UP_N_ROWS ESCAPE "[%dA"
anatofuz
parents:
diff changeset
59 #define ANSI_DOWN_N_ROWS ESCAPE "[%dB"
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 #define EditLineConstString(str) L##str
anatofuz
parents:
diff changeset
64 #define EditLineStringFormatSpec "%ls"
anatofuz
parents:
diff changeset
65
anatofuz
parents:
diff changeset
66 #else
anatofuz
parents:
diff changeset
67
anatofuz
parents:
diff changeset
68 #define EditLineConstString(str) str
anatofuz
parents:
diff changeset
69 #define EditLineStringFormatSpec "%s"
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 // use #defines so wide version functions and structs will resolve to old
anatofuz
parents:
diff changeset
72 // versions for case of libedit not built with wide char support
anatofuz
parents:
diff changeset
73 #define history_w history
anatofuz
parents:
diff changeset
74 #define history_winit history_init
anatofuz
parents:
diff changeset
75 #define history_wend history_end
anatofuz
parents:
diff changeset
76 #define HistoryW History
anatofuz
parents:
diff changeset
77 #define HistEventW HistEvent
anatofuz
parents:
diff changeset
78 #define LineInfoW LineInfo
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 #define el_wgets el_gets
anatofuz
parents:
diff changeset
81 #define el_wgetc el_getc
anatofuz
parents:
diff changeset
82 #define el_wpush el_push
anatofuz
parents:
diff changeset
83 #define el_wparse el_parse
anatofuz
parents:
diff changeset
84 #define el_wset el_set
anatofuz
parents:
diff changeset
85 #define el_wget el_get
anatofuz
parents:
diff changeset
86 #define el_wline el_line
anatofuz
parents:
diff changeset
87 #define el_winsertstr el_insertstr
anatofuz
parents:
diff changeset
88 #define el_wdeletestr el_deletestr
anatofuz
parents:
diff changeset
89
anatofuz
parents:
diff changeset
90 #endif // #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
91
anatofuz
parents:
diff changeset
92 bool IsOnlySpaces(const EditLineStringType &content) {
anatofuz
parents:
diff changeset
93 for (wchar_t ch : content) {
anatofuz
parents:
diff changeset
94 if (ch != EditLineCharType(' '))
anatofuz
parents:
diff changeset
95 return false;
anatofuz
parents:
diff changeset
96 }
anatofuz
parents:
diff changeset
97 return true;
anatofuz
parents:
diff changeset
98 }
anatofuz
parents:
diff changeset
99
anatofuz
parents:
diff changeset
100 static int GetOperation(HistoryOperation op) {
anatofuz
parents:
diff changeset
101 // The naming used by editline for the history operations is counter
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
102 // intuitive to how it's used in LLDB's editline implementation.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
103 //
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
104 // - The H_LAST returns the oldest entry in the history.
150
anatofuz
parents:
diff changeset
105 //
anatofuz
parents:
diff changeset
106 // - The H_PREV operation returns the previous element in the history, which
anatofuz
parents:
diff changeset
107 // is newer than the current one.
anatofuz
parents:
diff changeset
108 //
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
109 // - The H_CURR returns the current entry in the history.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
110 //
150
anatofuz
parents:
diff changeset
111 // - The H_NEXT operation returns the next element in the history, which is
anatofuz
parents:
diff changeset
112 // older than the current one.
anatofuz
parents:
diff changeset
113 //
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
114 // - The H_FIRST returns the most recent entry in the history.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
115 //
150
anatofuz
parents:
diff changeset
116 // The naming of the enum entries match the semantic meaning.
anatofuz
parents:
diff changeset
117 switch(op) {
anatofuz
parents:
diff changeset
118 case HistoryOperation::Oldest:
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
119 return H_LAST;
150
anatofuz
parents:
diff changeset
120 case HistoryOperation::Older:
anatofuz
parents:
diff changeset
121 return H_NEXT;
anatofuz
parents:
diff changeset
122 case HistoryOperation::Current:
anatofuz
parents:
diff changeset
123 return H_CURR;
anatofuz
parents:
diff changeset
124 case HistoryOperation::Newer:
anatofuz
parents:
diff changeset
125 return H_PREV;
anatofuz
parents:
diff changeset
126 case HistoryOperation::Newest:
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
127 return H_FIRST;
150
anatofuz
parents:
diff changeset
128 }
anatofuz
parents:
diff changeset
129 llvm_unreachable("Fully covered switch!");
anatofuz
parents:
diff changeset
130 }
anatofuz
parents:
diff changeset
131
anatofuz
parents:
diff changeset
132
anatofuz
parents:
diff changeset
133 EditLineStringType CombineLines(const std::vector<EditLineStringType> &lines) {
anatofuz
parents:
diff changeset
134 EditLineStringStreamType combined_stream;
anatofuz
parents:
diff changeset
135 for (EditLineStringType line : lines) {
anatofuz
parents:
diff changeset
136 combined_stream << line.c_str() << "\n";
anatofuz
parents:
diff changeset
137 }
anatofuz
parents:
diff changeset
138 return combined_stream.str();
anatofuz
parents:
diff changeset
139 }
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 std::vector<EditLineStringType> SplitLines(const EditLineStringType &input) {
anatofuz
parents:
diff changeset
142 std::vector<EditLineStringType> result;
anatofuz
parents:
diff changeset
143 size_t start = 0;
anatofuz
parents:
diff changeset
144 while (start < input.length()) {
anatofuz
parents:
diff changeset
145 size_t end = input.find('\n', start);
anatofuz
parents:
diff changeset
146 if (end == std::string::npos) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
147 result.push_back(input.substr(start));
150
anatofuz
parents:
diff changeset
148 break;
anatofuz
parents:
diff changeset
149 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
150 result.push_back(input.substr(start, end - start));
150
anatofuz
parents:
diff changeset
151 start = end + 1;
anatofuz
parents:
diff changeset
152 }
anatofuz
parents:
diff changeset
153 return result;
anatofuz
parents:
diff changeset
154 }
anatofuz
parents:
diff changeset
155
anatofuz
parents:
diff changeset
156 EditLineStringType FixIndentation(const EditLineStringType &line,
anatofuz
parents:
diff changeset
157 int indent_correction) {
anatofuz
parents:
diff changeset
158 if (indent_correction == 0)
anatofuz
parents:
diff changeset
159 return line;
anatofuz
parents:
diff changeset
160 if (indent_correction < 0)
anatofuz
parents:
diff changeset
161 return line.substr(-indent_correction);
anatofuz
parents:
diff changeset
162 return EditLineStringType(indent_correction, EditLineCharType(' ')) + line;
anatofuz
parents:
diff changeset
163 }
anatofuz
parents:
diff changeset
164
anatofuz
parents:
diff changeset
165 int GetIndentation(const EditLineStringType &line) {
anatofuz
parents:
diff changeset
166 int space_count = 0;
anatofuz
parents:
diff changeset
167 for (EditLineCharType ch : line) {
anatofuz
parents:
diff changeset
168 if (ch != EditLineCharType(' '))
anatofuz
parents:
diff changeset
169 break;
anatofuz
parents:
diff changeset
170 ++space_count;
anatofuz
parents:
diff changeset
171 }
anatofuz
parents:
diff changeset
172 return space_count;
anatofuz
parents:
diff changeset
173 }
anatofuz
parents:
diff changeset
174
anatofuz
parents:
diff changeset
175 bool IsInputPending(FILE *file) {
anatofuz
parents:
diff changeset
176 // FIXME: This will be broken on Windows if we ever re-enable Editline. You
anatofuz
parents:
diff changeset
177 // can't use select
anatofuz
parents:
diff changeset
178 // on something that isn't a socket. This will have to be re-written to not
anatofuz
parents:
diff changeset
179 // use a FILE*, but instead use some kind of yet-to-be-created abstraction
anatofuz
parents:
diff changeset
180 // that select-like functionality on non-socket objects.
anatofuz
parents:
diff changeset
181 const int fd = fileno(file);
anatofuz
parents:
diff changeset
182 SelectHelper select_helper;
anatofuz
parents:
diff changeset
183 select_helper.SetTimeout(std::chrono::microseconds(0));
anatofuz
parents:
diff changeset
184 select_helper.FDSetRead(fd);
anatofuz
parents:
diff changeset
185 return select_helper.Select().Success();
anatofuz
parents:
diff changeset
186 }
anatofuz
parents:
diff changeset
187
anatofuz
parents:
diff changeset
188 namespace lldb_private {
anatofuz
parents:
diff changeset
189 namespace line_editor {
anatofuz
parents:
diff changeset
190 typedef std::weak_ptr<EditlineHistory> EditlineHistoryWP;
anatofuz
parents:
diff changeset
191
anatofuz
parents:
diff changeset
192 // EditlineHistory objects are sometimes shared between multiple Editline
anatofuz
parents:
diff changeset
193 // instances with the same program name.
anatofuz
parents:
diff changeset
194
anatofuz
parents:
diff changeset
195 class EditlineHistory {
anatofuz
parents:
diff changeset
196 private:
anatofuz
parents:
diff changeset
197 // Use static GetHistory() function to get a EditlineHistorySP to one of
anatofuz
parents:
diff changeset
198 // these objects
anatofuz
parents:
diff changeset
199 EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries)
anatofuz
parents:
diff changeset
200 : m_history(nullptr), m_event(), m_prefix(prefix), m_path() {
anatofuz
parents:
diff changeset
201 m_history = history_winit();
anatofuz
parents:
diff changeset
202 history_w(m_history, &m_event, H_SETSIZE, size);
anatofuz
parents:
diff changeset
203 if (unique_entries)
anatofuz
parents:
diff changeset
204 history_w(m_history, &m_event, H_SETUNIQUE, 1);
anatofuz
parents:
diff changeset
205 }
anatofuz
parents:
diff changeset
206
anatofuz
parents:
diff changeset
207 const char *GetHistoryFilePath() {
anatofuz
parents:
diff changeset
208 // Compute the history path lazily.
anatofuz
parents:
diff changeset
209 if (m_path.empty() && m_history && !m_prefix.empty()) {
anatofuz
parents:
diff changeset
210 llvm::SmallString<128> lldb_history_file;
anatofuz
parents:
diff changeset
211 llvm::sys::path::home_directory(lldb_history_file);
anatofuz
parents:
diff changeset
212 llvm::sys::path::append(lldb_history_file, ".lldb");
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 // LLDB stores its history in ~/.lldb/. If for some reason this directory
anatofuz
parents:
diff changeset
215 // isn't writable or cannot be created, history won't be available.
anatofuz
parents:
diff changeset
216 if (!llvm::sys::fs::create_directory(lldb_history_file)) {
anatofuz
parents:
diff changeset
217 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
218 std::string filename = m_prefix + "-widehistory";
anatofuz
parents:
diff changeset
219 #else
anatofuz
parents:
diff changeset
220 std::string filename = m_prefix + "-history";
anatofuz
parents:
diff changeset
221 #endif
anatofuz
parents:
diff changeset
222 llvm::sys::path::append(lldb_history_file, filename);
anatofuz
parents:
diff changeset
223 m_path = std::string(lldb_history_file.str());
anatofuz
parents:
diff changeset
224 }
anatofuz
parents:
diff changeset
225 }
anatofuz
parents:
diff changeset
226
anatofuz
parents:
diff changeset
227 if (m_path.empty())
anatofuz
parents:
diff changeset
228 return nullptr;
anatofuz
parents:
diff changeset
229
anatofuz
parents:
diff changeset
230 return m_path.c_str();
anatofuz
parents:
diff changeset
231 }
anatofuz
parents:
diff changeset
232
anatofuz
parents:
diff changeset
233 public:
anatofuz
parents:
diff changeset
234 ~EditlineHistory() {
anatofuz
parents:
diff changeset
235 Save();
anatofuz
parents:
diff changeset
236
anatofuz
parents:
diff changeset
237 if (m_history) {
anatofuz
parents:
diff changeset
238 history_wend(m_history);
anatofuz
parents:
diff changeset
239 m_history = nullptr;
anatofuz
parents:
diff changeset
240 }
anatofuz
parents:
diff changeset
241 }
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 static EditlineHistorySP GetHistory(const std::string &prefix) {
anatofuz
parents:
diff changeset
244 typedef std::map<std::string, EditlineHistoryWP> WeakHistoryMap;
anatofuz
parents:
diff changeset
245 static std::recursive_mutex g_mutex;
anatofuz
parents:
diff changeset
246 static WeakHistoryMap g_weak_map;
anatofuz
parents:
diff changeset
247 std::lock_guard<std::recursive_mutex> guard(g_mutex);
anatofuz
parents:
diff changeset
248 WeakHistoryMap::const_iterator pos = g_weak_map.find(prefix);
anatofuz
parents:
diff changeset
249 EditlineHistorySP history_sp;
anatofuz
parents:
diff changeset
250 if (pos != g_weak_map.end()) {
anatofuz
parents:
diff changeset
251 history_sp = pos->second.lock();
anatofuz
parents:
diff changeset
252 if (history_sp)
anatofuz
parents:
diff changeset
253 return history_sp;
anatofuz
parents:
diff changeset
254 g_weak_map.erase(pos);
anatofuz
parents:
diff changeset
255 }
anatofuz
parents:
diff changeset
256 history_sp.reset(new EditlineHistory(prefix, 800, true));
anatofuz
parents:
diff changeset
257 g_weak_map[prefix] = history_sp;
anatofuz
parents:
diff changeset
258 return history_sp;
anatofuz
parents:
diff changeset
259 }
anatofuz
parents:
diff changeset
260
anatofuz
parents:
diff changeset
261 bool IsValid() const { return m_history != nullptr; }
anatofuz
parents:
diff changeset
262
anatofuz
parents:
diff changeset
263 HistoryW *GetHistoryPtr() { return m_history; }
anatofuz
parents:
diff changeset
264
anatofuz
parents:
diff changeset
265 void Enter(const EditLineCharType *line_cstr) {
anatofuz
parents:
diff changeset
266 if (m_history)
anatofuz
parents:
diff changeset
267 history_w(m_history, &m_event, H_ENTER, line_cstr);
anatofuz
parents:
diff changeset
268 }
anatofuz
parents:
diff changeset
269
anatofuz
parents:
diff changeset
270 bool Load() {
anatofuz
parents:
diff changeset
271 if (m_history) {
anatofuz
parents:
diff changeset
272 const char *path = GetHistoryFilePath();
anatofuz
parents:
diff changeset
273 if (path) {
anatofuz
parents:
diff changeset
274 history_w(m_history, &m_event, H_LOAD, path);
anatofuz
parents:
diff changeset
275 return true;
anatofuz
parents:
diff changeset
276 }
anatofuz
parents:
diff changeset
277 }
anatofuz
parents:
diff changeset
278 return false;
anatofuz
parents:
diff changeset
279 }
anatofuz
parents:
diff changeset
280
anatofuz
parents:
diff changeset
281 bool Save() {
anatofuz
parents:
diff changeset
282 if (m_history) {
anatofuz
parents:
diff changeset
283 const char *path = GetHistoryFilePath();
anatofuz
parents:
diff changeset
284 if (path) {
anatofuz
parents:
diff changeset
285 history_w(m_history, &m_event, H_SAVE, path);
anatofuz
parents:
diff changeset
286 return true;
anatofuz
parents:
diff changeset
287 }
anatofuz
parents:
diff changeset
288 }
anatofuz
parents:
diff changeset
289 return false;
anatofuz
parents:
diff changeset
290 }
anatofuz
parents:
diff changeset
291
anatofuz
parents:
diff changeset
292 protected:
anatofuz
parents:
diff changeset
293 HistoryW *m_history; // The history object
anatofuz
parents:
diff changeset
294 HistEventW m_event; // The history event needed to contain all history events
anatofuz
parents:
diff changeset
295 std::string m_prefix; // The prefix name (usually the editline program name)
anatofuz
parents:
diff changeset
296 // to use when loading/saving history
anatofuz
parents:
diff changeset
297 std::string m_path; // Path to the history file
anatofuz
parents:
diff changeset
298 };
anatofuz
parents:
diff changeset
299 }
anatofuz
parents:
diff changeset
300 }
anatofuz
parents:
diff changeset
301
anatofuz
parents:
diff changeset
302 // Editline private methods
anatofuz
parents:
diff changeset
303
anatofuz
parents:
diff changeset
304 void Editline::SetBaseLineNumber(int line_number) {
anatofuz
parents:
diff changeset
305 m_base_line_number = line_number;
anatofuz
parents:
diff changeset
306 m_line_number_digits =
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
307 std::max<int>(3, std::to_string(line_number).length() + 1);
150
anatofuz
parents:
diff changeset
308 }
anatofuz
parents:
diff changeset
309
anatofuz
parents:
diff changeset
310 std::string Editline::PromptForIndex(int line_index) {
anatofuz
parents:
diff changeset
311 bool use_line_numbers = m_multiline_enabled && m_base_line_number > 0;
anatofuz
parents:
diff changeset
312 std::string prompt = m_set_prompt;
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
313 if (use_line_numbers && prompt.length() == 0)
150
anatofuz
parents:
diff changeset
314 prompt = ": ";
anatofuz
parents:
diff changeset
315 std::string continuation_prompt = prompt;
anatofuz
parents:
diff changeset
316 if (m_set_continuation_prompt.length() > 0) {
anatofuz
parents:
diff changeset
317 continuation_prompt = m_set_continuation_prompt;
anatofuz
parents:
diff changeset
318
anatofuz
parents:
diff changeset
319 // Ensure that both prompts are the same length through space padding
anatofuz
parents:
diff changeset
320 while (continuation_prompt.length() < prompt.length()) {
anatofuz
parents:
diff changeset
321 continuation_prompt += ' ';
anatofuz
parents:
diff changeset
322 }
anatofuz
parents:
diff changeset
323 while (prompt.length() < continuation_prompt.length()) {
anatofuz
parents:
diff changeset
324 prompt += ' ';
anatofuz
parents:
diff changeset
325 }
anatofuz
parents:
diff changeset
326 }
anatofuz
parents:
diff changeset
327
anatofuz
parents:
diff changeset
328 if (use_line_numbers) {
anatofuz
parents:
diff changeset
329 StreamString prompt_stream;
anatofuz
parents:
diff changeset
330 prompt_stream.Printf(
anatofuz
parents:
diff changeset
331 "%*d%s", m_line_number_digits, m_base_line_number + line_index,
anatofuz
parents:
diff changeset
332 (line_index == 0) ? prompt.c_str() : continuation_prompt.c_str());
anatofuz
parents:
diff changeset
333 return std::string(std::move(prompt_stream.GetString()));
anatofuz
parents:
diff changeset
334 }
anatofuz
parents:
diff changeset
335 return (line_index == 0) ? prompt : continuation_prompt;
anatofuz
parents:
diff changeset
336 }
anatofuz
parents:
diff changeset
337
anatofuz
parents:
diff changeset
338 void Editline::SetCurrentLine(int line_index) {
anatofuz
parents:
diff changeset
339 m_current_line_index = line_index;
anatofuz
parents:
diff changeset
340 m_current_prompt = PromptForIndex(line_index);
anatofuz
parents:
diff changeset
341 }
anatofuz
parents:
diff changeset
342
anatofuz
parents:
diff changeset
343 int Editline::GetPromptWidth() { return (int)PromptForIndex(0).length(); }
anatofuz
parents:
diff changeset
344
anatofuz
parents:
diff changeset
345 bool Editline::IsEmacs() {
anatofuz
parents:
diff changeset
346 const char *editor;
anatofuz
parents:
diff changeset
347 el_get(m_editline, EL_EDITOR, &editor);
anatofuz
parents:
diff changeset
348 return editor[0] == 'e';
anatofuz
parents:
diff changeset
349 }
anatofuz
parents:
diff changeset
350
anatofuz
parents:
diff changeset
351 bool Editline::IsOnlySpaces() {
anatofuz
parents:
diff changeset
352 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
353 for (const EditLineCharType *character = info->buffer;
anatofuz
parents:
diff changeset
354 character < info->lastchar; character++) {
anatofuz
parents:
diff changeset
355 if (*character != ' ')
anatofuz
parents:
diff changeset
356 return false;
anatofuz
parents:
diff changeset
357 }
anatofuz
parents:
diff changeset
358 return true;
anatofuz
parents:
diff changeset
359 }
anatofuz
parents:
diff changeset
360
anatofuz
parents:
diff changeset
361 int Editline::GetLineIndexForLocation(CursorLocation location, int cursor_row) {
anatofuz
parents:
diff changeset
362 int line = 0;
anatofuz
parents:
diff changeset
363 if (location == CursorLocation::EditingPrompt ||
anatofuz
parents:
diff changeset
364 location == CursorLocation::BlockEnd ||
anatofuz
parents:
diff changeset
365 location == CursorLocation::EditingCursor) {
anatofuz
parents:
diff changeset
366 for (unsigned index = 0; index < m_current_line_index; index++) {
anatofuz
parents:
diff changeset
367 line += CountRowsForLine(m_input_lines[index]);
anatofuz
parents:
diff changeset
368 }
anatofuz
parents:
diff changeset
369 if (location == CursorLocation::EditingCursor) {
anatofuz
parents:
diff changeset
370 line += cursor_row;
anatofuz
parents:
diff changeset
371 } else if (location == CursorLocation::BlockEnd) {
anatofuz
parents:
diff changeset
372 for (unsigned index = m_current_line_index; index < m_input_lines.size();
anatofuz
parents:
diff changeset
373 index++) {
anatofuz
parents:
diff changeset
374 line += CountRowsForLine(m_input_lines[index]);
anatofuz
parents:
diff changeset
375 }
anatofuz
parents:
diff changeset
376 --line;
anatofuz
parents:
diff changeset
377 }
anatofuz
parents:
diff changeset
378 }
anatofuz
parents:
diff changeset
379 return line;
anatofuz
parents:
diff changeset
380 }
anatofuz
parents:
diff changeset
381
anatofuz
parents:
diff changeset
382 void Editline::MoveCursor(CursorLocation from, CursorLocation to) {
anatofuz
parents:
diff changeset
383 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
384 int editline_cursor_position =
anatofuz
parents:
diff changeset
385 (int)((info->cursor - info->buffer) + GetPromptWidth());
anatofuz
parents:
diff changeset
386 int editline_cursor_row = editline_cursor_position / m_terminal_width;
anatofuz
parents:
diff changeset
387
anatofuz
parents:
diff changeset
388 // Determine relative starting and ending lines
anatofuz
parents:
diff changeset
389 int fromLine = GetLineIndexForLocation(from, editline_cursor_row);
anatofuz
parents:
diff changeset
390 int toLine = GetLineIndexForLocation(to, editline_cursor_row);
anatofuz
parents:
diff changeset
391 if (toLine != fromLine) {
anatofuz
parents:
diff changeset
392 fprintf(m_output_file,
anatofuz
parents:
diff changeset
393 (toLine > fromLine) ? ANSI_DOWN_N_ROWS : ANSI_UP_N_ROWS,
anatofuz
parents:
diff changeset
394 std::abs(toLine - fromLine));
anatofuz
parents:
diff changeset
395 }
anatofuz
parents:
diff changeset
396
anatofuz
parents:
diff changeset
397 // Determine target column
anatofuz
parents:
diff changeset
398 int toColumn = 1;
anatofuz
parents:
diff changeset
399 if (to == CursorLocation::EditingCursor) {
anatofuz
parents:
diff changeset
400 toColumn =
anatofuz
parents:
diff changeset
401 editline_cursor_position - (editline_cursor_row * m_terminal_width) + 1;
anatofuz
parents:
diff changeset
402 } else if (to == CursorLocation::BlockEnd && !m_input_lines.empty()) {
anatofuz
parents:
diff changeset
403 toColumn =
anatofuz
parents:
diff changeset
404 ((m_input_lines[m_input_lines.size() - 1].length() + GetPromptWidth()) %
anatofuz
parents:
diff changeset
405 80) +
anatofuz
parents:
diff changeset
406 1;
anatofuz
parents:
diff changeset
407 }
anatofuz
parents:
diff changeset
408 fprintf(m_output_file, ANSI_SET_COLUMN_N, toColumn);
anatofuz
parents:
diff changeset
409 }
anatofuz
parents:
diff changeset
410
anatofuz
parents:
diff changeset
411 void Editline::DisplayInput(int firstIndex) {
anatofuz
parents:
diff changeset
412 fprintf(m_output_file, ANSI_SET_COLUMN_N ANSI_CLEAR_BELOW, 1);
anatofuz
parents:
diff changeset
413 int line_count = (int)m_input_lines.size();
anatofuz
parents:
diff changeset
414 const char *faint = m_color_prompts ? ANSI_FAINT : "";
anatofuz
parents:
diff changeset
415 const char *unfaint = m_color_prompts ? ANSI_UNFAINT : "";
anatofuz
parents:
diff changeset
416
anatofuz
parents:
diff changeset
417 for (int index = firstIndex; index < line_count; index++) {
anatofuz
parents:
diff changeset
418 fprintf(m_output_file, "%s"
anatofuz
parents:
diff changeset
419 "%s"
anatofuz
parents:
diff changeset
420 "%s" EditLineStringFormatSpec " ",
anatofuz
parents:
diff changeset
421 faint, PromptForIndex(index).c_str(), unfaint,
anatofuz
parents:
diff changeset
422 m_input_lines[index].c_str());
anatofuz
parents:
diff changeset
423 if (index < line_count - 1)
anatofuz
parents:
diff changeset
424 fprintf(m_output_file, "\n");
anatofuz
parents:
diff changeset
425 }
anatofuz
parents:
diff changeset
426 }
anatofuz
parents:
diff changeset
427
anatofuz
parents:
diff changeset
428 int Editline::CountRowsForLine(const EditLineStringType &content) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
429 std::string prompt =
150
anatofuz
parents:
diff changeset
430 PromptForIndex(0); // Prompt width is constant during an edit session
anatofuz
parents:
diff changeset
431 int line_length = (int)(content.length() + prompt.length());
anatofuz
parents:
diff changeset
432 return (line_length / m_terminal_width) + 1;
anatofuz
parents:
diff changeset
433 }
anatofuz
parents:
diff changeset
434
anatofuz
parents:
diff changeset
435 void Editline::SaveEditedLine() {
anatofuz
parents:
diff changeset
436 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
437 m_input_lines[m_current_line_index] =
anatofuz
parents:
diff changeset
438 EditLineStringType(info->buffer, info->lastchar - info->buffer);
anatofuz
parents:
diff changeset
439 }
anatofuz
parents:
diff changeset
440
anatofuz
parents:
diff changeset
441 StringList Editline::GetInputAsStringList(int line_count) {
anatofuz
parents:
diff changeset
442 StringList lines;
anatofuz
parents:
diff changeset
443 for (EditLineStringType line : m_input_lines) {
anatofuz
parents:
diff changeset
444 if (line_count == 0)
anatofuz
parents:
diff changeset
445 break;
anatofuz
parents:
diff changeset
446 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
447 lines.AppendString(m_utf8conv.to_bytes(line));
anatofuz
parents:
diff changeset
448 #else
anatofuz
parents:
diff changeset
449 lines.AppendString(line);
anatofuz
parents:
diff changeset
450 #endif
anatofuz
parents:
diff changeset
451 --line_count;
anatofuz
parents:
diff changeset
452 }
anatofuz
parents:
diff changeset
453 return lines;
anatofuz
parents:
diff changeset
454 }
anatofuz
parents:
diff changeset
455
anatofuz
parents:
diff changeset
456 unsigned char Editline::RecallHistory(HistoryOperation op) {
anatofuz
parents:
diff changeset
457 assert(op == HistoryOperation::Older || op == HistoryOperation::Newer);
anatofuz
parents:
diff changeset
458 if (!m_history_sp || !m_history_sp->IsValid())
anatofuz
parents:
diff changeset
459 return CC_ERROR;
anatofuz
parents:
diff changeset
460
anatofuz
parents:
diff changeset
461 HistoryW *pHistory = m_history_sp->GetHistoryPtr();
anatofuz
parents:
diff changeset
462 HistEventW history_event;
anatofuz
parents:
diff changeset
463 std::vector<EditLineStringType> new_input_lines;
anatofuz
parents:
diff changeset
464
anatofuz
parents:
diff changeset
465 // Treat moving from the "live" entry differently
anatofuz
parents:
diff changeset
466 if (!m_in_history) {
anatofuz
parents:
diff changeset
467 switch (op) {
anatofuz
parents:
diff changeset
468 case HistoryOperation::Newer:
anatofuz
parents:
diff changeset
469 return CC_ERROR; // Can't go newer than the "live" entry
anatofuz
parents:
diff changeset
470 case HistoryOperation::Older: {
anatofuz
parents:
diff changeset
471 if (history_w(pHistory, &history_event,
anatofuz
parents:
diff changeset
472 GetOperation(HistoryOperation::Newest)) == -1)
anatofuz
parents:
diff changeset
473 return CC_ERROR;
anatofuz
parents:
diff changeset
474 // Save any edits to the "live" entry in case we return by moving forward
anatofuz
parents:
diff changeset
475 // in history (it would be more bash-like to save over any current entry,
anatofuz
parents:
diff changeset
476 // but libedit doesn't offer the ability to add entries anywhere except
anatofuz
parents:
diff changeset
477 // the end.)
anatofuz
parents:
diff changeset
478 SaveEditedLine();
anatofuz
parents:
diff changeset
479 m_live_history_lines = m_input_lines;
anatofuz
parents:
diff changeset
480 m_in_history = true;
anatofuz
parents:
diff changeset
481 } break;
anatofuz
parents:
diff changeset
482 default:
anatofuz
parents:
diff changeset
483 llvm_unreachable("unsupported history direction");
anatofuz
parents:
diff changeset
484 }
anatofuz
parents:
diff changeset
485 } else {
anatofuz
parents:
diff changeset
486 if (history_w(pHistory, &history_event, GetOperation(op)) == -1) {
anatofuz
parents:
diff changeset
487 switch (op) {
anatofuz
parents:
diff changeset
488 case HistoryOperation::Older:
anatofuz
parents:
diff changeset
489 // Can't move earlier than the earliest entry.
anatofuz
parents:
diff changeset
490 return CC_ERROR;
anatofuz
parents:
diff changeset
491 case HistoryOperation::Newer:
anatofuz
parents:
diff changeset
492 // Moving to newer-than-the-newest entry yields the "live" entry.
anatofuz
parents:
diff changeset
493 new_input_lines = m_live_history_lines;
anatofuz
parents:
diff changeset
494 m_in_history = false;
anatofuz
parents:
diff changeset
495 break;
anatofuz
parents:
diff changeset
496 default:
anatofuz
parents:
diff changeset
497 llvm_unreachable("unsupported history direction");
anatofuz
parents:
diff changeset
498 }
anatofuz
parents:
diff changeset
499 }
anatofuz
parents:
diff changeset
500 }
anatofuz
parents:
diff changeset
501
anatofuz
parents:
diff changeset
502 // If we're pulling the lines from history, split them apart
anatofuz
parents:
diff changeset
503 if (m_in_history)
anatofuz
parents:
diff changeset
504 new_input_lines = SplitLines(history_event.str);
anatofuz
parents:
diff changeset
505
anatofuz
parents:
diff changeset
506 // Erase the current edit session and replace it with a new one
anatofuz
parents:
diff changeset
507 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
anatofuz
parents:
diff changeset
508 m_input_lines = new_input_lines;
anatofuz
parents:
diff changeset
509 DisplayInput();
anatofuz
parents:
diff changeset
510
anatofuz
parents:
diff changeset
511 // Prepare to edit the last line when moving to previous entry, or the first
anatofuz
parents:
diff changeset
512 // line when moving to next entry
anatofuz
parents:
diff changeset
513 switch (op) {
anatofuz
parents:
diff changeset
514 case HistoryOperation::Older:
anatofuz
parents:
diff changeset
515 m_current_line_index = (int)m_input_lines.size() - 1;
anatofuz
parents:
diff changeset
516 break;
anatofuz
parents:
diff changeset
517 case HistoryOperation::Newer:
anatofuz
parents:
diff changeset
518 m_current_line_index = 0;
anatofuz
parents:
diff changeset
519 break;
anatofuz
parents:
diff changeset
520 default:
anatofuz
parents:
diff changeset
521 llvm_unreachable("unsupported history direction");
anatofuz
parents:
diff changeset
522 }
anatofuz
parents:
diff changeset
523 SetCurrentLine(m_current_line_index);
anatofuz
parents:
diff changeset
524 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
525 return CC_NEWLINE;
anatofuz
parents:
diff changeset
526 }
anatofuz
parents:
diff changeset
527
anatofuz
parents:
diff changeset
528 int Editline::GetCharacter(EditLineGetCharType *c) {
anatofuz
parents:
diff changeset
529 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
530
anatofuz
parents:
diff changeset
531 // Paint a faint version of the desired prompt over the version libedit draws
anatofuz
parents:
diff changeset
532 // (will only be requested if colors are supported)
anatofuz
parents:
diff changeset
533 if (m_needs_prompt_repaint) {
anatofuz
parents:
diff changeset
534 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
535 fprintf(m_output_file, "%s"
anatofuz
parents:
diff changeset
536 "%s"
anatofuz
parents:
diff changeset
537 "%s",
anatofuz
parents:
diff changeset
538 ANSI_FAINT, Prompt(), ANSI_UNFAINT);
anatofuz
parents:
diff changeset
539 MoveCursor(CursorLocation::EditingPrompt, CursorLocation::EditingCursor);
anatofuz
parents:
diff changeset
540 m_needs_prompt_repaint = false;
anatofuz
parents:
diff changeset
541 }
anatofuz
parents:
diff changeset
542
anatofuz
parents:
diff changeset
543 if (m_multiline_enabled) {
anatofuz
parents:
diff changeset
544 // Detect when the number of rows used for this input line changes due to
anatofuz
parents:
diff changeset
545 // an edit
anatofuz
parents:
diff changeset
546 int lineLength = (int)((info->lastchar - info->buffer) + GetPromptWidth());
anatofuz
parents:
diff changeset
547 int new_line_rows = (lineLength / m_terminal_width) + 1;
anatofuz
parents:
diff changeset
548 if (m_current_line_rows != -1 && new_line_rows != m_current_line_rows) {
anatofuz
parents:
diff changeset
549 // Respond by repainting the current state from this line on
anatofuz
parents:
diff changeset
550 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
551 SaveEditedLine();
anatofuz
parents:
diff changeset
552 DisplayInput(m_current_line_index);
anatofuz
parents:
diff changeset
553 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
anatofuz
parents:
diff changeset
554 }
anatofuz
parents:
diff changeset
555 m_current_line_rows = new_line_rows;
anatofuz
parents:
diff changeset
556 }
anatofuz
parents:
diff changeset
557
anatofuz
parents:
diff changeset
558 // Read an actual character
anatofuz
parents:
diff changeset
559 while (true) {
anatofuz
parents:
diff changeset
560 lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
anatofuz
parents:
diff changeset
561 char ch = 0;
anatofuz
parents:
diff changeset
562
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
563 if (m_terminal_size_has_changed)
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
564 ApplyTerminalSizeChange();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
565
150
anatofuz
parents:
diff changeset
566 // This mutex is locked by our caller (GetLine). Unlock it while we read a
anatofuz
parents:
diff changeset
567 // character (blocking operation), so we do not hold the mutex
anatofuz
parents:
diff changeset
568 // indefinitely. This gives a chance for someone to interrupt us. After
anatofuz
parents:
diff changeset
569 // Read returns, immediately lock the mutex again and check if we were
anatofuz
parents:
diff changeset
570 // interrupted.
anatofuz
parents:
diff changeset
571 m_output_mutex.unlock();
anatofuz
parents:
diff changeset
572 int read_count =
anatofuz
parents:
diff changeset
573 m_input_connection.Read(&ch, 1, llvm::None, status, nullptr);
anatofuz
parents:
diff changeset
574 m_output_mutex.lock();
anatofuz
parents:
diff changeset
575 if (m_editor_status == EditorStatus::Interrupted) {
anatofuz
parents:
diff changeset
576 while (read_count > 0 && status == lldb::eConnectionStatusSuccess)
anatofuz
parents:
diff changeset
577 read_count =
anatofuz
parents:
diff changeset
578 m_input_connection.Read(&ch, 1, llvm::None, status, nullptr);
anatofuz
parents:
diff changeset
579 lldbassert(status == lldb::eConnectionStatusInterrupted);
anatofuz
parents:
diff changeset
580 return 0;
anatofuz
parents:
diff changeset
581 }
anatofuz
parents:
diff changeset
582
anatofuz
parents:
diff changeset
583 if (read_count) {
anatofuz
parents:
diff changeset
584 if (CompleteCharacter(ch, *c))
anatofuz
parents:
diff changeset
585 return 1;
anatofuz
parents:
diff changeset
586 } else {
anatofuz
parents:
diff changeset
587 switch (status) {
anatofuz
parents:
diff changeset
588 case lldb::eConnectionStatusSuccess: // Success
anatofuz
parents:
diff changeset
589 break;
anatofuz
parents:
diff changeset
590
anatofuz
parents:
diff changeset
591 case lldb::eConnectionStatusInterrupted:
anatofuz
parents:
diff changeset
592 llvm_unreachable("Interrupts should have been handled above.");
anatofuz
parents:
diff changeset
593
anatofuz
parents:
diff changeset
594 case lldb::eConnectionStatusError: // Check GetError() for details
anatofuz
parents:
diff changeset
595 case lldb::eConnectionStatusTimedOut: // Request timed out
anatofuz
parents:
diff changeset
596 case lldb::eConnectionStatusEndOfFile: // End-of-file encountered
anatofuz
parents:
diff changeset
597 case lldb::eConnectionStatusNoConnection: // No connection
anatofuz
parents:
diff changeset
598 case lldb::eConnectionStatusLostConnection: // Lost connection while
anatofuz
parents:
diff changeset
599 // connected to a valid
anatofuz
parents:
diff changeset
600 // connection
anatofuz
parents:
diff changeset
601 m_editor_status = EditorStatus::EndOfInput;
anatofuz
parents:
diff changeset
602 return 0;
anatofuz
parents:
diff changeset
603 }
anatofuz
parents:
diff changeset
604 }
anatofuz
parents:
diff changeset
605 }
anatofuz
parents:
diff changeset
606 }
anatofuz
parents:
diff changeset
607
anatofuz
parents:
diff changeset
608 const char *Editline::Prompt() {
anatofuz
parents:
diff changeset
609 if (m_color_prompts)
anatofuz
parents:
diff changeset
610 m_needs_prompt_repaint = true;
anatofuz
parents:
diff changeset
611 return m_current_prompt.c_str();
anatofuz
parents:
diff changeset
612 }
anatofuz
parents:
diff changeset
613
anatofuz
parents:
diff changeset
614 unsigned char Editline::BreakLineCommand(int ch) {
anatofuz
parents:
diff changeset
615 // Preserve any content beyond the cursor, truncate and save the current line
anatofuz
parents:
diff changeset
616 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
617 auto current_line =
anatofuz
parents:
diff changeset
618 EditLineStringType(info->buffer, info->cursor - info->buffer);
anatofuz
parents:
diff changeset
619 auto new_line_fragment =
anatofuz
parents:
diff changeset
620 EditLineStringType(info->cursor, info->lastchar - info->cursor);
anatofuz
parents:
diff changeset
621 m_input_lines[m_current_line_index] = current_line;
anatofuz
parents:
diff changeset
622
anatofuz
parents:
diff changeset
623 // Ignore whitespace-only extra fragments when breaking a line
anatofuz
parents:
diff changeset
624 if (::IsOnlySpaces(new_line_fragment))
anatofuz
parents:
diff changeset
625 new_line_fragment = EditLineConstString("");
anatofuz
parents:
diff changeset
626
anatofuz
parents:
diff changeset
627 // Establish the new cursor position at the start of a line when inserting a
anatofuz
parents:
diff changeset
628 // line break
anatofuz
parents:
diff changeset
629 m_revert_cursor_index = 0;
anatofuz
parents:
diff changeset
630
anatofuz
parents:
diff changeset
631 // Don't perform automatic formatting when pasting
anatofuz
parents:
diff changeset
632 if (!IsInputPending(m_input_file)) {
anatofuz
parents:
diff changeset
633 // Apply smart indentation
anatofuz
parents:
diff changeset
634 if (m_fix_indentation_callback) {
anatofuz
parents:
diff changeset
635 StringList lines = GetInputAsStringList(m_current_line_index + 1);
anatofuz
parents:
diff changeset
636 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
637 lines.AppendString(m_utf8conv.to_bytes(new_line_fragment));
anatofuz
parents:
diff changeset
638 #else
anatofuz
parents:
diff changeset
639 lines.AppendString(new_line_fragment);
anatofuz
parents:
diff changeset
640 #endif
anatofuz
parents:
diff changeset
641
anatofuz
parents:
diff changeset
642 int indent_correction = m_fix_indentation_callback(
anatofuz
parents:
diff changeset
643 this, lines, 0, m_fix_indentation_callback_baton);
anatofuz
parents:
diff changeset
644 new_line_fragment = FixIndentation(new_line_fragment, indent_correction);
anatofuz
parents:
diff changeset
645 m_revert_cursor_index = GetIndentation(new_line_fragment);
anatofuz
parents:
diff changeset
646 }
anatofuz
parents:
diff changeset
647 }
anatofuz
parents:
diff changeset
648
anatofuz
parents:
diff changeset
649 // Insert the new line and repaint everything from the split line on down
anatofuz
parents:
diff changeset
650 m_input_lines.insert(m_input_lines.begin() + m_current_line_index + 1,
anatofuz
parents:
diff changeset
651 new_line_fragment);
anatofuz
parents:
diff changeset
652 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
653 DisplayInput(m_current_line_index);
anatofuz
parents:
diff changeset
654
anatofuz
parents:
diff changeset
655 // Reposition the cursor to the right line and prepare to edit the new line
anatofuz
parents:
diff changeset
656 SetCurrentLine(m_current_line_index + 1);
anatofuz
parents:
diff changeset
657 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
658 return CC_NEWLINE;
anatofuz
parents:
diff changeset
659 }
anatofuz
parents:
diff changeset
660
anatofuz
parents:
diff changeset
661 unsigned char Editline::EndOrAddLineCommand(int ch) {
anatofuz
parents:
diff changeset
662 // Don't perform end of input detection when pasting, always treat this as a
anatofuz
parents:
diff changeset
663 // line break
anatofuz
parents:
diff changeset
664 if (IsInputPending(m_input_file)) {
anatofuz
parents:
diff changeset
665 return BreakLineCommand(ch);
anatofuz
parents:
diff changeset
666 }
anatofuz
parents:
diff changeset
667
anatofuz
parents:
diff changeset
668 // Save any edits to this line
anatofuz
parents:
diff changeset
669 SaveEditedLine();
anatofuz
parents:
diff changeset
670
anatofuz
parents:
diff changeset
671 // If this is the end of the last line, consider whether to add a line
anatofuz
parents:
diff changeset
672 // instead
anatofuz
parents:
diff changeset
673 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
674 if (m_current_line_index == m_input_lines.size() - 1 &&
anatofuz
parents:
diff changeset
675 info->cursor == info->lastchar) {
anatofuz
parents:
diff changeset
676 if (m_is_input_complete_callback) {
anatofuz
parents:
diff changeset
677 auto lines = GetInputAsStringList();
anatofuz
parents:
diff changeset
678 if (!m_is_input_complete_callback(this, lines,
anatofuz
parents:
diff changeset
679 m_is_input_complete_callback_baton)) {
anatofuz
parents:
diff changeset
680 return BreakLineCommand(ch);
anatofuz
parents:
diff changeset
681 }
anatofuz
parents:
diff changeset
682
anatofuz
parents:
diff changeset
683 // The completion test is allowed to change the input lines when complete
anatofuz
parents:
diff changeset
684 m_input_lines.clear();
anatofuz
parents:
diff changeset
685 for (unsigned index = 0; index < lines.GetSize(); index++) {
anatofuz
parents:
diff changeset
686 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
687 m_input_lines.insert(m_input_lines.end(),
anatofuz
parents:
diff changeset
688 m_utf8conv.from_bytes(lines[index]));
anatofuz
parents:
diff changeset
689 #else
anatofuz
parents:
diff changeset
690 m_input_lines.insert(m_input_lines.end(), lines[index]);
anatofuz
parents:
diff changeset
691 #endif
anatofuz
parents:
diff changeset
692 }
anatofuz
parents:
diff changeset
693 }
anatofuz
parents:
diff changeset
694 }
anatofuz
parents:
diff changeset
695 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd);
anatofuz
parents:
diff changeset
696 fprintf(m_output_file, "\n");
anatofuz
parents:
diff changeset
697 m_editor_status = EditorStatus::Complete;
anatofuz
parents:
diff changeset
698 return CC_NEWLINE;
anatofuz
parents:
diff changeset
699 }
anatofuz
parents:
diff changeset
700
anatofuz
parents:
diff changeset
701 unsigned char Editline::DeleteNextCharCommand(int ch) {
anatofuz
parents:
diff changeset
702 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
anatofuz
parents:
diff changeset
703
anatofuz
parents:
diff changeset
704 // Just delete the next character normally if possible
anatofuz
parents:
diff changeset
705 if (info->cursor < info->lastchar) {
anatofuz
parents:
diff changeset
706 info->cursor++;
anatofuz
parents:
diff changeset
707 el_deletestr(m_editline, 1);
anatofuz
parents:
diff changeset
708 return CC_REFRESH;
anatofuz
parents:
diff changeset
709 }
anatofuz
parents:
diff changeset
710
anatofuz
parents:
diff changeset
711 // Fail when at the end of the last line, except when ^D is pressed on the
anatofuz
parents:
diff changeset
712 // line is empty, in which case it is treated as EOF
anatofuz
parents:
diff changeset
713 if (m_current_line_index == m_input_lines.size() - 1) {
anatofuz
parents:
diff changeset
714 if (ch == 4 && info->buffer == info->lastchar) {
anatofuz
parents:
diff changeset
715 fprintf(m_output_file, "^D\n");
anatofuz
parents:
diff changeset
716 m_editor_status = EditorStatus::EndOfInput;
anatofuz
parents:
diff changeset
717 return CC_EOF;
anatofuz
parents:
diff changeset
718 }
anatofuz
parents:
diff changeset
719 return CC_ERROR;
anatofuz
parents:
diff changeset
720 }
anatofuz
parents:
diff changeset
721
anatofuz
parents:
diff changeset
722 // Prepare to combine this line with the one below
anatofuz
parents:
diff changeset
723 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
724
anatofuz
parents:
diff changeset
725 // Insert the next line of text at the cursor and restore the cursor position
anatofuz
parents:
diff changeset
726 const EditLineCharType *cursor = info->cursor;
anatofuz
parents:
diff changeset
727 el_winsertstr(m_editline, m_input_lines[m_current_line_index + 1].c_str());
anatofuz
parents:
diff changeset
728 info->cursor = cursor;
anatofuz
parents:
diff changeset
729 SaveEditedLine();
anatofuz
parents:
diff changeset
730
anatofuz
parents:
diff changeset
731 // Delete the extra line
anatofuz
parents:
diff changeset
732 m_input_lines.erase(m_input_lines.begin() + m_current_line_index + 1);
anatofuz
parents:
diff changeset
733
anatofuz
parents:
diff changeset
734 // Clear and repaint from this line on down
anatofuz
parents:
diff changeset
735 DisplayInput(m_current_line_index);
anatofuz
parents:
diff changeset
736 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
anatofuz
parents:
diff changeset
737 return CC_REFRESH;
anatofuz
parents:
diff changeset
738 }
anatofuz
parents:
diff changeset
739
anatofuz
parents:
diff changeset
740 unsigned char Editline::DeletePreviousCharCommand(int ch) {
anatofuz
parents:
diff changeset
741 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
anatofuz
parents:
diff changeset
742
anatofuz
parents:
diff changeset
743 // Just delete the previous character normally when not at the start of a
anatofuz
parents:
diff changeset
744 // line
anatofuz
parents:
diff changeset
745 if (info->cursor > info->buffer) {
anatofuz
parents:
diff changeset
746 el_deletestr(m_editline, 1);
anatofuz
parents:
diff changeset
747 return CC_REFRESH;
anatofuz
parents:
diff changeset
748 }
anatofuz
parents:
diff changeset
749
anatofuz
parents:
diff changeset
750 // No prior line and no prior character? Let the user know
anatofuz
parents:
diff changeset
751 if (m_current_line_index == 0)
anatofuz
parents:
diff changeset
752 return CC_ERROR;
anatofuz
parents:
diff changeset
753
anatofuz
parents:
diff changeset
754 // No prior character, but prior line? Combine with the line above
anatofuz
parents:
diff changeset
755 SaveEditedLine();
anatofuz
parents:
diff changeset
756 SetCurrentLine(m_current_line_index - 1);
anatofuz
parents:
diff changeset
757 auto priorLine = m_input_lines[m_current_line_index];
anatofuz
parents:
diff changeset
758 m_input_lines.erase(m_input_lines.begin() + m_current_line_index);
anatofuz
parents:
diff changeset
759 m_input_lines[m_current_line_index] =
anatofuz
parents:
diff changeset
760 priorLine + m_input_lines[m_current_line_index];
anatofuz
parents:
diff changeset
761
anatofuz
parents:
diff changeset
762 // Repaint from the new line down
anatofuz
parents:
diff changeset
763 fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
anatofuz
parents:
diff changeset
764 CountRowsForLine(priorLine), 1);
anatofuz
parents:
diff changeset
765 DisplayInput(m_current_line_index);
anatofuz
parents:
diff changeset
766
anatofuz
parents:
diff changeset
767 // Put the cursor back where libedit expects it to be before returning to
anatofuz
parents:
diff changeset
768 // editing by telling libedit about the newly inserted text
anatofuz
parents:
diff changeset
769 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
770 el_winsertstr(m_editline, priorLine.c_str());
anatofuz
parents:
diff changeset
771 return CC_REDISPLAY;
anatofuz
parents:
diff changeset
772 }
anatofuz
parents:
diff changeset
773
anatofuz
parents:
diff changeset
774 unsigned char Editline::PreviousLineCommand(int ch) {
anatofuz
parents:
diff changeset
775 SaveEditedLine();
anatofuz
parents:
diff changeset
776
anatofuz
parents:
diff changeset
777 if (m_current_line_index == 0) {
anatofuz
parents:
diff changeset
778 return RecallHistory(HistoryOperation::Older);
anatofuz
parents:
diff changeset
779 }
anatofuz
parents:
diff changeset
780
anatofuz
parents:
diff changeset
781 // Start from a known location
anatofuz
parents:
diff changeset
782 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
783
anatofuz
parents:
diff changeset
784 // Treat moving up from a blank last line as a deletion of that line
anatofuz
parents:
diff changeset
785 if (m_current_line_index == m_input_lines.size() - 1 && IsOnlySpaces()) {
anatofuz
parents:
diff changeset
786 m_input_lines.erase(m_input_lines.begin() + m_current_line_index);
anatofuz
parents:
diff changeset
787 fprintf(m_output_file, ANSI_CLEAR_BELOW);
anatofuz
parents:
diff changeset
788 }
anatofuz
parents:
diff changeset
789
anatofuz
parents:
diff changeset
790 SetCurrentLine(m_current_line_index - 1);
anatofuz
parents:
diff changeset
791 fprintf(m_output_file, ANSI_UP_N_ROWS ANSI_SET_COLUMN_N,
anatofuz
parents:
diff changeset
792 CountRowsForLine(m_input_lines[m_current_line_index]), 1);
anatofuz
parents:
diff changeset
793 return CC_NEWLINE;
anatofuz
parents:
diff changeset
794 }
anatofuz
parents:
diff changeset
795
anatofuz
parents:
diff changeset
796 unsigned char Editline::NextLineCommand(int ch) {
anatofuz
parents:
diff changeset
797 SaveEditedLine();
anatofuz
parents:
diff changeset
798
anatofuz
parents:
diff changeset
799 // Handle attempts to move down from the last line
anatofuz
parents:
diff changeset
800 if (m_current_line_index == m_input_lines.size() - 1) {
anatofuz
parents:
diff changeset
801 // Don't add an extra line if the existing last line is blank, move through
anatofuz
parents:
diff changeset
802 // history instead
anatofuz
parents:
diff changeset
803 if (IsOnlySpaces()) {
anatofuz
parents:
diff changeset
804 return RecallHistory(HistoryOperation::Newer);
anatofuz
parents:
diff changeset
805 }
anatofuz
parents:
diff changeset
806
anatofuz
parents:
diff changeset
807 // Determine indentation for the new line
anatofuz
parents:
diff changeset
808 int indentation = 0;
anatofuz
parents:
diff changeset
809 if (m_fix_indentation_callback) {
anatofuz
parents:
diff changeset
810 StringList lines = GetInputAsStringList();
anatofuz
parents:
diff changeset
811 lines.AppendString("");
anatofuz
parents:
diff changeset
812 indentation = m_fix_indentation_callback(
anatofuz
parents:
diff changeset
813 this, lines, 0, m_fix_indentation_callback_baton);
anatofuz
parents:
diff changeset
814 }
anatofuz
parents:
diff changeset
815 m_input_lines.insert(
anatofuz
parents:
diff changeset
816 m_input_lines.end(),
anatofuz
parents:
diff changeset
817 EditLineStringType(indentation, EditLineCharType(' ')));
anatofuz
parents:
diff changeset
818 }
anatofuz
parents:
diff changeset
819
anatofuz
parents:
diff changeset
820 // Move down past the current line using newlines to force scrolling if
anatofuz
parents:
diff changeset
821 // needed
anatofuz
parents:
diff changeset
822 SetCurrentLine(m_current_line_index + 1);
anatofuz
parents:
diff changeset
823 const LineInfoW *info = el_wline(m_editline);
anatofuz
parents:
diff changeset
824 int cursor_position = (int)((info->cursor - info->buffer) + GetPromptWidth());
anatofuz
parents:
diff changeset
825 int cursor_row = cursor_position / m_terminal_width;
anatofuz
parents:
diff changeset
826 for (int line_count = 0; line_count < m_current_line_rows - cursor_row;
anatofuz
parents:
diff changeset
827 line_count++) {
anatofuz
parents:
diff changeset
828 fprintf(m_output_file, "\n");
anatofuz
parents:
diff changeset
829 }
anatofuz
parents:
diff changeset
830 return CC_NEWLINE;
anatofuz
parents:
diff changeset
831 }
anatofuz
parents:
diff changeset
832
anatofuz
parents:
diff changeset
833 unsigned char Editline::PreviousHistoryCommand(int ch) {
anatofuz
parents:
diff changeset
834 SaveEditedLine();
anatofuz
parents:
diff changeset
835
anatofuz
parents:
diff changeset
836 return RecallHistory(HistoryOperation::Older);
anatofuz
parents:
diff changeset
837 }
anatofuz
parents:
diff changeset
838
anatofuz
parents:
diff changeset
839 unsigned char Editline::NextHistoryCommand(int ch) {
anatofuz
parents:
diff changeset
840 SaveEditedLine();
anatofuz
parents:
diff changeset
841
anatofuz
parents:
diff changeset
842 return RecallHistory(HistoryOperation::Newer);
anatofuz
parents:
diff changeset
843 }
anatofuz
parents:
diff changeset
844
anatofuz
parents:
diff changeset
845 unsigned char Editline::FixIndentationCommand(int ch) {
anatofuz
parents:
diff changeset
846 if (!m_fix_indentation_callback)
anatofuz
parents:
diff changeset
847 return CC_NORM;
anatofuz
parents:
diff changeset
848
anatofuz
parents:
diff changeset
849 // Insert the character typed before proceeding
anatofuz
parents:
diff changeset
850 EditLineCharType inserted[] = {(EditLineCharType)ch, 0};
anatofuz
parents:
diff changeset
851 el_winsertstr(m_editline, inserted);
anatofuz
parents:
diff changeset
852 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
anatofuz
parents:
diff changeset
853 int cursor_position = info->cursor - info->buffer;
anatofuz
parents:
diff changeset
854
anatofuz
parents:
diff changeset
855 // Save the edits and determine the correct indentation level
anatofuz
parents:
diff changeset
856 SaveEditedLine();
anatofuz
parents:
diff changeset
857 StringList lines = GetInputAsStringList(m_current_line_index + 1);
anatofuz
parents:
diff changeset
858 int indent_correction = m_fix_indentation_callback(
anatofuz
parents:
diff changeset
859 this, lines, cursor_position, m_fix_indentation_callback_baton);
anatofuz
parents:
diff changeset
860
anatofuz
parents:
diff changeset
861 // If it is already correct no special work is needed
anatofuz
parents:
diff changeset
862 if (indent_correction == 0)
anatofuz
parents:
diff changeset
863 return CC_REFRESH;
anatofuz
parents:
diff changeset
864
anatofuz
parents:
diff changeset
865 // Change the indentation level of the line
anatofuz
parents:
diff changeset
866 std::string currentLine = lines.GetStringAtIndex(m_current_line_index);
anatofuz
parents:
diff changeset
867 if (indent_correction > 0) {
anatofuz
parents:
diff changeset
868 currentLine = currentLine.insert(0, indent_correction, ' ');
anatofuz
parents:
diff changeset
869 } else {
anatofuz
parents:
diff changeset
870 currentLine = currentLine.erase(0, -indent_correction);
anatofuz
parents:
diff changeset
871 }
anatofuz
parents:
diff changeset
872 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
873 m_input_lines[m_current_line_index] = m_utf8conv.from_bytes(currentLine);
anatofuz
parents:
diff changeset
874 #else
anatofuz
parents:
diff changeset
875 m_input_lines[m_current_line_index] = currentLine;
anatofuz
parents:
diff changeset
876 #endif
anatofuz
parents:
diff changeset
877
anatofuz
parents:
diff changeset
878 // Update the display to reflect the change
anatofuz
parents:
diff changeset
879 MoveCursor(CursorLocation::EditingCursor, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
880 DisplayInput(m_current_line_index);
anatofuz
parents:
diff changeset
881
anatofuz
parents:
diff changeset
882 // Reposition the cursor back on the original line and prepare to restart
anatofuz
parents:
diff changeset
883 // editing with a new cursor position
anatofuz
parents:
diff changeset
884 SetCurrentLine(m_current_line_index);
anatofuz
parents:
diff changeset
885 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
886 m_revert_cursor_index = cursor_position + indent_correction;
anatofuz
parents:
diff changeset
887 return CC_NEWLINE;
anatofuz
parents:
diff changeset
888 }
anatofuz
parents:
diff changeset
889
anatofuz
parents:
diff changeset
890 unsigned char Editline::RevertLineCommand(int ch) {
anatofuz
parents:
diff changeset
891 el_winsertstr(m_editline, m_input_lines[m_current_line_index].c_str());
anatofuz
parents:
diff changeset
892 if (m_revert_cursor_index >= 0) {
anatofuz
parents:
diff changeset
893 LineInfoW *info = const_cast<LineInfoW *>(el_wline(m_editline));
anatofuz
parents:
diff changeset
894 info->cursor = info->buffer + m_revert_cursor_index;
anatofuz
parents:
diff changeset
895 if (info->cursor > info->lastchar) {
anatofuz
parents:
diff changeset
896 info->cursor = info->lastchar;
anatofuz
parents:
diff changeset
897 }
anatofuz
parents:
diff changeset
898 m_revert_cursor_index = -1;
anatofuz
parents:
diff changeset
899 }
anatofuz
parents:
diff changeset
900 return CC_REFRESH;
anatofuz
parents:
diff changeset
901 }
anatofuz
parents:
diff changeset
902
anatofuz
parents:
diff changeset
903 unsigned char Editline::BufferStartCommand(int ch) {
anatofuz
parents:
diff changeset
904 SaveEditedLine();
anatofuz
parents:
diff changeset
905 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
anatofuz
parents:
diff changeset
906 SetCurrentLine(0);
anatofuz
parents:
diff changeset
907 m_revert_cursor_index = 0;
anatofuz
parents:
diff changeset
908 return CC_NEWLINE;
anatofuz
parents:
diff changeset
909 }
anatofuz
parents:
diff changeset
910
anatofuz
parents:
diff changeset
911 unsigned char Editline::BufferEndCommand(int ch) {
anatofuz
parents:
diff changeset
912 SaveEditedLine();
anatofuz
parents:
diff changeset
913 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockEnd);
anatofuz
parents:
diff changeset
914 SetCurrentLine((int)m_input_lines.size() - 1);
anatofuz
parents:
diff changeset
915 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingPrompt);
anatofuz
parents:
diff changeset
916 return CC_NEWLINE;
anatofuz
parents:
diff changeset
917 }
anatofuz
parents:
diff changeset
918
anatofuz
parents:
diff changeset
919 /// Prints completions and their descriptions to the given file. Only the
anatofuz
parents:
diff changeset
920 /// completions in the interval [start, end) are printed.
anatofuz
parents:
diff changeset
921 static void
anatofuz
parents:
diff changeset
922 PrintCompletion(FILE *output_file,
anatofuz
parents:
diff changeset
923 llvm::ArrayRef<CompletionResult::Completion> results,
anatofuz
parents:
diff changeset
924 size_t max_len) {
anatofuz
parents:
diff changeset
925 for (const CompletionResult::Completion &c : results) {
anatofuz
parents:
diff changeset
926 fprintf(output_file, "\t%-*s", (int)max_len, c.GetCompletion().c_str());
anatofuz
parents:
diff changeset
927 if (!c.GetDescription().empty())
anatofuz
parents:
diff changeset
928 fprintf(output_file, " -- %s", c.GetDescription().c_str());
anatofuz
parents:
diff changeset
929 fprintf(output_file, "\n");
anatofuz
parents:
diff changeset
930 }
anatofuz
parents:
diff changeset
931 }
anatofuz
parents:
diff changeset
932
anatofuz
parents:
diff changeset
933 static void
anatofuz
parents:
diff changeset
934 DisplayCompletions(::EditLine *editline, FILE *output_file,
anatofuz
parents:
diff changeset
935 llvm::ArrayRef<CompletionResult::Completion> results) {
anatofuz
parents:
diff changeset
936 assert(!results.empty());
anatofuz
parents:
diff changeset
937
anatofuz
parents:
diff changeset
938 fprintf(output_file, "\n" ANSI_CLEAR_BELOW "Available completions:\n");
anatofuz
parents:
diff changeset
939 const size_t page_size = 40;
anatofuz
parents:
diff changeset
940 bool all = false;
anatofuz
parents:
diff changeset
941
anatofuz
parents:
diff changeset
942 auto longest =
anatofuz
parents:
diff changeset
943 std::max_element(results.begin(), results.end(), [](auto &c1, auto &c2) {
anatofuz
parents:
diff changeset
944 return c1.GetCompletion().size() < c2.GetCompletion().size();
anatofuz
parents:
diff changeset
945 });
anatofuz
parents:
diff changeset
946
anatofuz
parents:
diff changeset
947 const size_t max_len = longest->GetCompletion().size();
anatofuz
parents:
diff changeset
948
anatofuz
parents:
diff changeset
949 if (results.size() < page_size) {
anatofuz
parents:
diff changeset
950 PrintCompletion(output_file, results, max_len);
anatofuz
parents:
diff changeset
951 return;
anatofuz
parents:
diff changeset
952 }
anatofuz
parents:
diff changeset
953
anatofuz
parents:
diff changeset
954 size_t cur_pos = 0;
anatofuz
parents:
diff changeset
955 while (cur_pos < results.size()) {
anatofuz
parents:
diff changeset
956 size_t remaining = results.size() - cur_pos;
anatofuz
parents:
diff changeset
957 size_t next_size = all ? remaining : std::min(page_size, remaining);
anatofuz
parents:
diff changeset
958
anatofuz
parents:
diff changeset
959 PrintCompletion(output_file, results.slice(cur_pos, next_size), max_len);
anatofuz
parents:
diff changeset
960
anatofuz
parents:
diff changeset
961 cur_pos += next_size;
anatofuz
parents:
diff changeset
962
anatofuz
parents:
diff changeset
963 if (cur_pos >= results.size())
anatofuz
parents:
diff changeset
964 break;
anatofuz
parents:
diff changeset
965
anatofuz
parents:
diff changeset
966 fprintf(output_file, "More (Y/n/a): ");
anatofuz
parents:
diff changeset
967 char reply = 'n';
anatofuz
parents:
diff changeset
968 int got_char = el_getc(editline, &reply);
anatofuz
parents:
diff changeset
969 fprintf(output_file, "\n");
anatofuz
parents:
diff changeset
970 if (got_char == -1 || reply == 'n')
anatofuz
parents:
diff changeset
971 break;
anatofuz
parents:
diff changeset
972 if (reply == 'a')
anatofuz
parents:
diff changeset
973 all = true;
anatofuz
parents:
diff changeset
974 }
anatofuz
parents:
diff changeset
975 }
anatofuz
parents:
diff changeset
976
anatofuz
parents:
diff changeset
977 unsigned char Editline::TabCommand(int ch) {
anatofuz
parents:
diff changeset
978 if (m_completion_callback == nullptr)
anatofuz
parents:
diff changeset
979 return CC_ERROR;
anatofuz
parents:
diff changeset
980
anatofuz
parents:
diff changeset
981 const LineInfo *line_info = el_line(m_editline);
anatofuz
parents:
diff changeset
982
anatofuz
parents:
diff changeset
983 llvm::StringRef line(line_info->buffer,
anatofuz
parents:
diff changeset
984 line_info->lastchar - line_info->buffer);
anatofuz
parents:
diff changeset
985 unsigned cursor_index = line_info->cursor - line_info->buffer;
anatofuz
parents:
diff changeset
986 CompletionResult result;
anatofuz
parents:
diff changeset
987 CompletionRequest request(line, cursor_index, result);
anatofuz
parents:
diff changeset
988
anatofuz
parents:
diff changeset
989 m_completion_callback(request, m_completion_callback_baton);
anatofuz
parents:
diff changeset
990
anatofuz
parents:
diff changeset
991 llvm::ArrayRef<CompletionResult::Completion> results = result.GetResults();
anatofuz
parents:
diff changeset
992
anatofuz
parents:
diff changeset
993 StringList completions;
anatofuz
parents:
diff changeset
994 result.GetMatches(completions);
anatofuz
parents:
diff changeset
995
anatofuz
parents:
diff changeset
996 if (results.size() == 0)
anatofuz
parents:
diff changeset
997 return CC_ERROR;
anatofuz
parents:
diff changeset
998
anatofuz
parents:
diff changeset
999 if (results.size() == 1) {
anatofuz
parents:
diff changeset
1000 CompletionResult::Completion completion = results.front();
anatofuz
parents:
diff changeset
1001 switch (completion.GetMode()) {
anatofuz
parents:
diff changeset
1002 case CompletionMode::Normal: {
anatofuz
parents:
diff changeset
1003 std::string to_add = completion.GetCompletion();
anatofuz
parents:
diff changeset
1004 to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
anatofuz
parents:
diff changeset
1005 if (request.GetParsedArg().IsQuoted())
anatofuz
parents:
diff changeset
1006 to_add.push_back(request.GetParsedArg().GetQuoteChar());
anatofuz
parents:
diff changeset
1007 to_add.push_back(' ');
anatofuz
parents:
diff changeset
1008 el_insertstr(m_editline, to_add.c_str());
anatofuz
parents:
diff changeset
1009 break;
anatofuz
parents:
diff changeset
1010 }
anatofuz
parents:
diff changeset
1011 case CompletionMode::Partial: {
anatofuz
parents:
diff changeset
1012 std::string to_add = completion.GetCompletion();
anatofuz
parents:
diff changeset
1013 to_add = to_add.substr(request.GetCursorArgumentPrefix().size());
anatofuz
parents:
diff changeset
1014 el_insertstr(m_editline, to_add.c_str());
anatofuz
parents:
diff changeset
1015 break;
anatofuz
parents:
diff changeset
1016 }
anatofuz
parents:
diff changeset
1017 case CompletionMode::RewriteLine: {
anatofuz
parents:
diff changeset
1018 el_deletestr(m_editline, line_info->cursor - line_info->buffer);
anatofuz
parents:
diff changeset
1019 el_insertstr(m_editline, completion.GetCompletion().c_str());
anatofuz
parents:
diff changeset
1020 break;
anatofuz
parents:
diff changeset
1021 }
anatofuz
parents:
diff changeset
1022 }
anatofuz
parents:
diff changeset
1023 return CC_REDISPLAY;
anatofuz
parents:
diff changeset
1024 }
anatofuz
parents:
diff changeset
1025
anatofuz
parents:
diff changeset
1026 // If we get a longer match display that first.
anatofuz
parents:
diff changeset
1027 std::string longest_prefix = completions.LongestCommonPrefix();
anatofuz
parents:
diff changeset
1028 if (!longest_prefix.empty())
anatofuz
parents:
diff changeset
1029 longest_prefix =
anatofuz
parents:
diff changeset
1030 longest_prefix.substr(request.GetCursorArgumentPrefix().size());
anatofuz
parents:
diff changeset
1031 if (!longest_prefix.empty()) {
anatofuz
parents:
diff changeset
1032 el_insertstr(m_editline, longest_prefix.c_str());
anatofuz
parents:
diff changeset
1033 return CC_REDISPLAY;
anatofuz
parents:
diff changeset
1034 }
anatofuz
parents:
diff changeset
1035
anatofuz
parents:
diff changeset
1036 DisplayCompletions(m_editline, m_output_file, results);
anatofuz
parents:
diff changeset
1037
anatofuz
parents:
diff changeset
1038 DisplayInput();
anatofuz
parents:
diff changeset
1039 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
anatofuz
parents:
diff changeset
1040 return CC_REDISPLAY;
anatofuz
parents:
diff changeset
1041 }
anatofuz
parents:
diff changeset
1042
anatofuz
parents:
diff changeset
1043 void Editline::ConfigureEditor(bool multiline) {
anatofuz
parents:
diff changeset
1044 if (m_editline && m_multiline_enabled == multiline)
anatofuz
parents:
diff changeset
1045 return;
anatofuz
parents:
diff changeset
1046 m_multiline_enabled = multiline;
anatofuz
parents:
diff changeset
1047
anatofuz
parents:
diff changeset
1048 if (m_editline) {
anatofuz
parents:
diff changeset
1049 // Disable edit mode to stop the terminal from flushing all input during
anatofuz
parents:
diff changeset
1050 // the call to el_end() since we expect to have multiple editline instances
anatofuz
parents:
diff changeset
1051 // in this program.
anatofuz
parents:
diff changeset
1052 el_set(m_editline, EL_EDITMODE, 0);
anatofuz
parents:
diff changeset
1053 el_end(m_editline);
anatofuz
parents:
diff changeset
1054 }
anatofuz
parents:
diff changeset
1055
anatofuz
parents:
diff changeset
1056 m_editline =
anatofuz
parents:
diff changeset
1057 el_init(m_editor_name.c_str(), m_input_file, m_output_file, m_error_file);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1058 ApplyTerminalSizeChange();
150
anatofuz
parents:
diff changeset
1059
anatofuz
parents:
diff changeset
1060 if (m_history_sp && m_history_sp->IsValid()) {
anatofuz
parents:
diff changeset
1061 if (!m_history_sp->Load()) {
anatofuz
parents:
diff changeset
1062 fputs("Could not load history file\n.", m_output_file);
anatofuz
parents:
diff changeset
1063 }
anatofuz
parents:
diff changeset
1064 el_wset(m_editline, EL_HIST, history, m_history_sp->GetHistoryPtr());
anatofuz
parents:
diff changeset
1065 }
anatofuz
parents:
diff changeset
1066 el_set(m_editline, EL_CLIENTDATA, this);
anatofuz
parents:
diff changeset
1067 el_set(m_editline, EL_SIGNAL, 0);
anatofuz
parents:
diff changeset
1068 el_set(m_editline, EL_EDITOR, "emacs");
anatofuz
parents:
diff changeset
1069 el_set(m_editline, EL_PROMPT,
anatofuz
parents:
diff changeset
1070 (EditlinePromptCallbackType)([](EditLine *editline) {
anatofuz
parents:
diff changeset
1071 return Editline::InstanceFor(editline)->Prompt();
anatofuz
parents:
diff changeset
1072 }));
anatofuz
parents:
diff changeset
1073
anatofuz
parents:
diff changeset
1074 el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([](
anatofuz
parents:
diff changeset
1075 EditLine *editline, EditLineGetCharType *c) {
anatofuz
parents:
diff changeset
1076 return Editline::InstanceFor(editline)->GetCharacter(c);
anatofuz
parents:
diff changeset
1077 }));
anatofuz
parents:
diff changeset
1078
anatofuz
parents:
diff changeset
1079 // Commands used for multiline support, registered whether or not they're
anatofuz
parents:
diff changeset
1080 // used
anatofuz
parents:
diff changeset
1081 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-break-line"),
anatofuz
parents:
diff changeset
1082 EditLineConstString("Insert a line break"),
anatofuz
parents:
diff changeset
1083 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1084 return Editline::InstanceFor(editline)->BreakLineCommand(ch);
anatofuz
parents:
diff changeset
1085 }));
anatofuz
parents:
diff changeset
1086 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-end-or-add-line"),
anatofuz
parents:
diff changeset
1087 EditLineConstString("End editing or continue when incomplete"),
anatofuz
parents:
diff changeset
1088 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1089 return Editline::InstanceFor(editline)->EndOrAddLineCommand(ch);
anatofuz
parents:
diff changeset
1090 }));
anatofuz
parents:
diff changeset
1091 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-delete-next-char"),
anatofuz
parents:
diff changeset
1092 EditLineConstString("Delete next character"),
anatofuz
parents:
diff changeset
1093 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1094 return Editline::InstanceFor(editline)->DeleteNextCharCommand(ch);
anatofuz
parents:
diff changeset
1095 }));
anatofuz
parents:
diff changeset
1096 el_wset(
anatofuz
parents:
diff changeset
1097 m_editline, EL_ADDFN, EditLineConstString("lldb-delete-previous-char"),
anatofuz
parents:
diff changeset
1098 EditLineConstString("Delete previous character"),
anatofuz
parents:
diff changeset
1099 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1100 return Editline::InstanceFor(editline)->DeletePreviousCharCommand(ch);
anatofuz
parents:
diff changeset
1101 }));
anatofuz
parents:
diff changeset
1102 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-line"),
anatofuz
parents:
diff changeset
1103 EditLineConstString("Move to previous line"),
anatofuz
parents:
diff changeset
1104 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1105 return Editline::InstanceFor(editline)->PreviousLineCommand(ch);
anatofuz
parents:
diff changeset
1106 }));
anatofuz
parents:
diff changeset
1107 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-line"),
anatofuz
parents:
diff changeset
1108 EditLineConstString("Move to next line"),
anatofuz
parents:
diff changeset
1109 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1110 return Editline::InstanceFor(editline)->NextLineCommand(ch);
anatofuz
parents:
diff changeset
1111 }));
anatofuz
parents:
diff changeset
1112 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-previous-history"),
anatofuz
parents:
diff changeset
1113 EditLineConstString("Move to previous history"),
anatofuz
parents:
diff changeset
1114 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1115 return Editline::InstanceFor(editline)->PreviousHistoryCommand(ch);
anatofuz
parents:
diff changeset
1116 }));
anatofuz
parents:
diff changeset
1117 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-next-history"),
anatofuz
parents:
diff changeset
1118 EditLineConstString("Move to next history"),
anatofuz
parents:
diff changeset
1119 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1120 return Editline::InstanceFor(editline)->NextHistoryCommand(ch);
anatofuz
parents:
diff changeset
1121 }));
anatofuz
parents:
diff changeset
1122 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-start"),
anatofuz
parents:
diff changeset
1123 EditLineConstString("Move to start of buffer"),
anatofuz
parents:
diff changeset
1124 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1125 return Editline::InstanceFor(editline)->BufferStartCommand(ch);
anatofuz
parents:
diff changeset
1126 }));
anatofuz
parents:
diff changeset
1127 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-buffer-end"),
anatofuz
parents:
diff changeset
1128 EditLineConstString("Move to end of buffer"),
anatofuz
parents:
diff changeset
1129 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1130 return Editline::InstanceFor(editline)->BufferEndCommand(ch);
anatofuz
parents:
diff changeset
1131 }));
anatofuz
parents:
diff changeset
1132 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-fix-indentation"),
anatofuz
parents:
diff changeset
1133 EditLineConstString("Fix line indentation"),
anatofuz
parents:
diff changeset
1134 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1135 return Editline::InstanceFor(editline)->FixIndentationCommand(ch);
anatofuz
parents:
diff changeset
1136 }));
anatofuz
parents:
diff changeset
1137
anatofuz
parents:
diff changeset
1138 // Register the complete callback under two names for compatibility with
anatofuz
parents:
diff changeset
1139 // older clients using custom .editrc files (largely because libedit has a
anatofuz
parents:
diff changeset
1140 // bad bug where if you have a bind command that tries to bind to a function
anatofuz
parents:
diff changeset
1141 // name that doesn't exist, it can corrupt the heap and crash your process
anatofuz
parents:
diff changeset
1142 // later.)
anatofuz
parents:
diff changeset
1143 EditlineCommandCallbackType complete_callback = [](EditLine *editline,
anatofuz
parents:
diff changeset
1144 int ch) {
anatofuz
parents:
diff changeset
1145 return Editline::InstanceFor(editline)->TabCommand(ch);
anatofuz
parents:
diff changeset
1146 };
anatofuz
parents:
diff changeset
1147 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-complete"),
anatofuz
parents:
diff changeset
1148 EditLineConstString("Invoke completion"), complete_callback);
anatofuz
parents:
diff changeset
1149 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb_complete"),
anatofuz
parents:
diff changeset
1150 EditLineConstString("Invoke completion"), complete_callback);
anatofuz
parents:
diff changeset
1151
anatofuz
parents:
diff changeset
1152 // General bindings we don't mind being overridden
anatofuz
parents:
diff changeset
1153 if (!multiline) {
anatofuz
parents:
diff changeset
1154 el_set(m_editline, EL_BIND, "^r", "em-inc-search-prev",
anatofuz
parents:
diff changeset
1155 NULL); // Cycle through backwards search, entering string
anatofuz
parents:
diff changeset
1156 }
anatofuz
parents:
diff changeset
1157 el_set(m_editline, EL_BIND, "^w", "ed-delete-prev-word",
anatofuz
parents:
diff changeset
1158 NULL); // Delete previous word, behave like bash in emacs mode
anatofuz
parents:
diff changeset
1159 el_set(m_editline, EL_BIND, "\t", "lldb-complete",
anatofuz
parents:
diff changeset
1160 NULL); // Bind TAB to auto complete
anatofuz
parents:
diff changeset
1161
anatofuz
parents:
diff changeset
1162 // Allow ctrl-left-arrow and ctrl-right-arrow for navigation, behave like
anatofuz
parents:
diff changeset
1163 // bash in emacs mode.
anatofuz
parents:
diff changeset
1164 el_set(m_editline, EL_BIND, ESCAPE "[1;5C", "em-next-word", NULL);
anatofuz
parents:
diff changeset
1165 el_set(m_editline, EL_BIND, ESCAPE "[1;5D", "ed-prev-word", NULL);
anatofuz
parents:
diff changeset
1166 el_set(m_editline, EL_BIND, ESCAPE "[5C", "em-next-word", NULL);
anatofuz
parents:
diff changeset
1167 el_set(m_editline, EL_BIND, ESCAPE "[5D", "ed-prev-word", NULL);
anatofuz
parents:
diff changeset
1168 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[C", "em-next-word", NULL);
anatofuz
parents:
diff changeset
1169 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[D", "ed-prev-word", NULL);
anatofuz
parents:
diff changeset
1170
anatofuz
parents:
diff changeset
1171 // Allow user-specific customization prior to registering bindings we
anatofuz
parents:
diff changeset
1172 // absolutely require
anatofuz
parents:
diff changeset
1173 el_source(m_editline, nullptr);
anatofuz
parents:
diff changeset
1174
anatofuz
parents:
diff changeset
1175 // Register an internal binding that external developers shouldn't use
anatofuz
parents:
diff changeset
1176 el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"),
anatofuz
parents:
diff changeset
1177 EditLineConstString("Revert line to saved state"),
anatofuz
parents:
diff changeset
1178 (EditlineCommandCallbackType)([](EditLine *editline, int ch) {
anatofuz
parents:
diff changeset
1179 return Editline::InstanceFor(editline)->RevertLineCommand(ch);
anatofuz
parents:
diff changeset
1180 }));
anatofuz
parents:
diff changeset
1181
anatofuz
parents:
diff changeset
1182 // Register keys that perform auto-indent correction
anatofuz
parents:
diff changeset
1183 if (m_fix_indentation_callback && m_fix_indentation_callback_chars) {
anatofuz
parents:
diff changeset
1184 char bind_key[2] = {0, 0};
anatofuz
parents:
diff changeset
1185 const char *indent_chars = m_fix_indentation_callback_chars;
anatofuz
parents:
diff changeset
1186 while (*indent_chars) {
anatofuz
parents:
diff changeset
1187 bind_key[0] = *indent_chars;
anatofuz
parents:
diff changeset
1188 el_set(m_editline, EL_BIND, bind_key, "lldb-fix-indentation", NULL);
anatofuz
parents:
diff changeset
1189 ++indent_chars;
anatofuz
parents:
diff changeset
1190 }
anatofuz
parents:
diff changeset
1191 }
anatofuz
parents:
diff changeset
1192
anatofuz
parents:
diff changeset
1193 // Multi-line editor bindings
anatofuz
parents:
diff changeset
1194 if (multiline) {
anatofuz
parents:
diff changeset
1195 el_set(m_editline, EL_BIND, "\n", "lldb-end-or-add-line", NULL);
anatofuz
parents:
diff changeset
1196 el_set(m_editline, EL_BIND, "\r", "lldb-end-or-add-line", NULL);
anatofuz
parents:
diff changeset
1197 el_set(m_editline, EL_BIND, ESCAPE "\n", "lldb-break-line", NULL);
anatofuz
parents:
diff changeset
1198 el_set(m_editline, EL_BIND, ESCAPE "\r", "lldb-break-line", NULL);
anatofuz
parents:
diff changeset
1199 el_set(m_editline, EL_BIND, "^p", "lldb-previous-line", NULL);
anatofuz
parents:
diff changeset
1200 el_set(m_editline, EL_BIND, "^n", "lldb-next-line", NULL);
anatofuz
parents:
diff changeset
1201 el_set(m_editline, EL_BIND, "^?", "lldb-delete-previous-char", NULL);
anatofuz
parents:
diff changeset
1202 el_set(m_editline, EL_BIND, "^d", "lldb-delete-next-char", NULL);
anatofuz
parents:
diff changeset
1203 el_set(m_editline, EL_BIND, ESCAPE "[3~", "lldb-delete-next-char", NULL);
anatofuz
parents:
diff changeset
1204 el_set(m_editline, EL_BIND, ESCAPE "[\\^", "lldb-revert-line", NULL);
anatofuz
parents:
diff changeset
1205
anatofuz
parents:
diff changeset
1206 // Editor-specific bindings
anatofuz
parents:
diff changeset
1207 if (IsEmacs()) {
anatofuz
parents:
diff changeset
1208 el_set(m_editline, EL_BIND, ESCAPE "<", "lldb-buffer-start", NULL);
anatofuz
parents:
diff changeset
1209 el_set(m_editline, EL_BIND, ESCAPE ">", "lldb-buffer-end", NULL);
anatofuz
parents:
diff changeset
1210 el_set(m_editline, EL_BIND, ESCAPE "[A", "lldb-previous-line", NULL);
anatofuz
parents:
diff changeset
1211 el_set(m_editline, EL_BIND, ESCAPE "[B", "lldb-next-line", NULL);
anatofuz
parents:
diff changeset
1212 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[A", "lldb-previous-history",
anatofuz
parents:
diff changeset
1213 NULL);
anatofuz
parents:
diff changeset
1214 el_set(m_editline, EL_BIND, ESCAPE ESCAPE "[B", "lldb-next-history",
anatofuz
parents:
diff changeset
1215 NULL);
anatofuz
parents:
diff changeset
1216 el_set(m_editline, EL_BIND, ESCAPE "[1;3A", "lldb-previous-history",
anatofuz
parents:
diff changeset
1217 NULL);
anatofuz
parents:
diff changeset
1218 el_set(m_editline, EL_BIND, ESCAPE "[1;3B", "lldb-next-history", NULL);
anatofuz
parents:
diff changeset
1219 } else {
anatofuz
parents:
diff changeset
1220 el_set(m_editline, EL_BIND, "^H", "lldb-delete-previous-char", NULL);
anatofuz
parents:
diff changeset
1221
anatofuz
parents:
diff changeset
1222 el_set(m_editline, EL_BIND, "-a", ESCAPE "[A", "lldb-previous-line",
anatofuz
parents:
diff changeset
1223 NULL);
anatofuz
parents:
diff changeset
1224 el_set(m_editline, EL_BIND, "-a", ESCAPE "[B", "lldb-next-line", NULL);
anatofuz
parents:
diff changeset
1225 el_set(m_editline, EL_BIND, "-a", "x", "lldb-delete-next-char", NULL);
anatofuz
parents:
diff changeset
1226 el_set(m_editline, EL_BIND, "-a", "^H", "lldb-delete-previous-char",
anatofuz
parents:
diff changeset
1227 NULL);
anatofuz
parents:
diff changeset
1228 el_set(m_editline, EL_BIND, "-a", "^?", "lldb-delete-previous-char",
anatofuz
parents:
diff changeset
1229 NULL);
anatofuz
parents:
diff changeset
1230
anatofuz
parents:
diff changeset
1231 // Escape is absorbed exiting edit mode, so re-register important
anatofuz
parents:
diff changeset
1232 // sequences without the prefix
anatofuz
parents:
diff changeset
1233 el_set(m_editline, EL_BIND, "-a", "[A", "lldb-previous-line", NULL);
anatofuz
parents:
diff changeset
1234 el_set(m_editline, EL_BIND, "-a", "[B", "lldb-next-line", NULL);
anatofuz
parents:
diff changeset
1235 el_set(m_editline, EL_BIND, "-a", "[\\^", "lldb-revert-line", NULL);
anatofuz
parents:
diff changeset
1236 }
anatofuz
parents:
diff changeset
1237 }
anatofuz
parents:
diff changeset
1238 }
anatofuz
parents:
diff changeset
1239
anatofuz
parents:
diff changeset
1240 // Editline public methods
anatofuz
parents:
diff changeset
1241
anatofuz
parents:
diff changeset
1242 Editline *Editline::InstanceFor(EditLine *editline) {
anatofuz
parents:
diff changeset
1243 Editline *editor;
anatofuz
parents:
diff changeset
1244 el_get(editline, EL_CLIENTDATA, &editor);
anatofuz
parents:
diff changeset
1245 return editor;
anatofuz
parents:
diff changeset
1246 }
anatofuz
parents:
diff changeset
1247
anatofuz
parents:
diff changeset
1248 Editline::Editline(const char *editline_name, FILE *input_file,
anatofuz
parents:
diff changeset
1249 FILE *output_file, FILE *error_file, bool color_prompts)
anatofuz
parents:
diff changeset
1250 : m_editor_status(EditorStatus::Complete), m_color_prompts(color_prompts),
anatofuz
parents:
diff changeset
1251 m_input_file(input_file), m_output_file(output_file),
anatofuz
parents:
diff changeset
1252 m_error_file(error_file), m_input_connection(fileno(input_file), false) {
anatofuz
parents:
diff changeset
1253 // Get a shared history instance
anatofuz
parents:
diff changeset
1254 m_editor_name = (editline_name == nullptr) ? "lldb-tmp" : editline_name;
anatofuz
parents:
diff changeset
1255 m_history_sp = EditlineHistory::GetHistory(m_editor_name);
anatofuz
parents:
diff changeset
1256
anatofuz
parents:
diff changeset
1257 #ifdef USE_SETUPTERM_WORKAROUND
anatofuz
parents:
diff changeset
1258 if (m_output_file) {
anatofuz
parents:
diff changeset
1259 const int term_fd = fileno(m_output_file);
anatofuz
parents:
diff changeset
1260 if (term_fd != -1) {
anatofuz
parents:
diff changeset
1261 static std::mutex *g_init_terminal_fds_mutex_ptr = nullptr;
anatofuz
parents:
diff changeset
1262 static std::set<int> *g_init_terminal_fds_ptr = nullptr;
anatofuz
parents:
diff changeset
1263 static llvm::once_flag g_once_flag;
anatofuz
parents:
diff changeset
1264 llvm::call_once(g_once_flag, [&]() {
anatofuz
parents:
diff changeset
1265 g_init_terminal_fds_mutex_ptr =
anatofuz
parents:
diff changeset
1266 new std::mutex(); // NOTE: Leak to avoid C++ destructor chain issues
anatofuz
parents:
diff changeset
1267 g_init_terminal_fds_ptr = new std::set<int>(); // NOTE: Leak to avoid
anatofuz
parents:
diff changeset
1268 // C++ destructor chain
anatofuz
parents:
diff changeset
1269 // issues
anatofuz
parents:
diff changeset
1270 });
anatofuz
parents:
diff changeset
1271
anatofuz
parents:
diff changeset
1272 // We must make sure to initialize the terminal a given file descriptor
anatofuz
parents:
diff changeset
1273 // only once. If we do this multiple times, we start leaking memory.
anatofuz
parents:
diff changeset
1274 std::lock_guard<std::mutex> guard(*g_init_terminal_fds_mutex_ptr);
anatofuz
parents:
diff changeset
1275 if (g_init_terminal_fds_ptr->find(term_fd) ==
anatofuz
parents:
diff changeset
1276 g_init_terminal_fds_ptr->end()) {
anatofuz
parents:
diff changeset
1277 g_init_terminal_fds_ptr->insert(term_fd);
anatofuz
parents:
diff changeset
1278 setupterm((char *)0, term_fd, (int *)0);
anatofuz
parents:
diff changeset
1279 }
anatofuz
parents:
diff changeset
1280 }
anatofuz
parents:
diff changeset
1281 }
anatofuz
parents:
diff changeset
1282 #endif
anatofuz
parents:
diff changeset
1283 }
anatofuz
parents:
diff changeset
1284
anatofuz
parents:
diff changeset
1285 Editline::~Editline() {
anatofuz
parents:
diff changeset
1286 if (m_editline) {
anatofuz
parents:
diff changeset
1287 // Disable edit mode to stop the terminal from flushing all input during
anatofuz
parents:
diff changeset
1288 // the call to el_end() since we expect to have multiple editline instances
anatofuz
parents:
diff changeset
1289 // in this program.
anatofuz
parents:
diff changeset
1290 el_set(m_editline, EL_EDITMODE, 0);
anatofuz
parents:
diff changeset
1291 el_end(m_editline);
anatofuz
parents:
diff changeset
1292 m_editline = nullptr;
anatofuz
parents:
diff changeset
1293 }
anatofuz
parents:
diff changeset
1294
anatofuz
parents:
diff changeset
1295 // EditlineHistory objects are sometimes shared between multiple Editline
anatofuz
parents:
diff changeset
1296 // instances with the same program name. So just release our shared pointer
anatofuz
parents:
diff changeset
1297 // and if we are the last owner, it will save the history to the history save
anatofuz
parents:
diff changeset
1298 // file automatically.
anatofuz
parents:
diff changeset
1299 m_history_sp.reset();
anatofuz
parents:
diff changeset
1300 }
anatofuz
parents:
diff changeset
1301
anatofuz
parents:
diff changeset
1302 void Editline::SetPrompt(const char *prompt) {
anatofuz
parents:
diff changeset
1303 m_set_prompt = prompt == nullptr ? "" : prompt;
anatofuz
parents:
diff changeset
1304 }
anatofuz
parents:
diff changeset
1305
anatofuz
parents:
diff changeset
1306 void Editline::SetContinuationPrompt(const char *continuation_prompt) {
anatofuz
parents:
diff changeset
1307 m_set_continuation_prompt =
anatofuz
parents:
diff changeset
1308 continuation_prompt == nullptr ? "" : continuation_prompt;
anatofuz
parents:
diff changeset
1309 }
anatofuz
parents:
diff changeset
1310
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1311 void Editline::TerminalSizeChanged() { m_terminal_size_has_changed = 1; }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1312
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1313 void Editline::ApplyTerminalSizeChange() {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1314 if (!m_editline)
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1315 return;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1316
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1317 m_terminal_size_has_changed = 0;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1318 el_resize(m_editline);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1319 int columns;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1320 // This function is documenting as taking (const char *, void *) for the
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1321 // vararg part, but in reality in was consuming arguments until the first
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1322 // null pointer. This was fixed in libedit in April 2019
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1323 // <http://mail-index.netbsd.org/source-changes/2019/04/26/msg105454.html>,
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1324 // but we're keeping the workaround until a version with that fix is more
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1325 // widely available.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1326 if (el_get(m_editline, EL_GETTC, "co", &columns, nullptr) == 0) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1327 m_terminal_width = columns;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1328 if (m_current_line_rows != -1) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1329 const LineInfoW *info = el_wline(m_editline);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1330 int lineLength =
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1331 (int)((info->lastchar - info->buffer) + GetPromptWidth());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1332 m_current_line_rows = (lineLength / columns) + 1;
150
anatofuz
parents:
diff changeset
1333 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1334 } else {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1335 m_terminal_width = INT_MAX;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1336 m_current_line_rows = 1;
150
anatofuz
parents:
diff changeset
1337 }
anatofuz
parents:
diff changeset
1338 }
anatofuz
parents:
diff changeset
1339
anatofuz
parents:
diff changeset
1340 const char *Editline::GetPrompt() { return m_set_prompt.c_str(); }
anatofuz
parents:
diff changeset
1341
anatofuz
parents:
diff changeset
1342 uint32_t Editline::GetCurrentLine() { return m_current_line_index; }
anatofuz
parents:
diff changeset
1343
anatofuz
parents:
diff changeset
1344 bool Editline::Interrupt() {
anatofuz
parents:
diff changeset
1345 bool result = true;
anatofuz
parents:
diff changeset
1346 std::lock_guard<std::mutex> guard(m_output_mutex);
anatofuz
parents:
diff changeset
1347 if (m_editor_status == EditorStatus::Editing) {
anatofuz
parents:
diff changeset
1348 fprintf(m_output_file, "^C\n");
anatofuz
parents:
diff changeset
1349 result = m_input_connection.InterruptRead();
anatofuz
parents:
diff changeset
1350 }
anatofuz
parents:
diff changeset
1351 m_editor_status = EditorStatus::Interrupted;
anatofuz
parents:
diff changeset
1352 return result;
anatofuz
parents:
diff changeset
1353 }
anatofuz
parents:
diff changeset
1354
anatofuz
parents:
diff changeset
1355 bool Editline::Cancel() {
anatofuz
parents:
diff changeset
1356 bool result = true;
anatofuz
parents:
diff changeset
1357 std::lock_guard<std::mutex> guard(m_output_mutex);
anatofuz
parents:
diff changeset
1358 if (m_editor_status == EditorStatus::Editing) {
anatofuz
parents:
diff changeset
1359 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
anatofuz
parents:
diff changeset
1360 fprintf(m_output_file, ANSI_CLEAR_BELOW);
anatofuz
parents:
diff changeset
1361 result = m_input_connection.InterruptRead();
anatofuz
parents:
diff changeset
1362 }
anatofuz
parents:
diff changeset
1363 m_editor_status = EditorStatus::Interrupted;
anatofuz
parents:
diff changeset
1364 return result;
anatofuz
parents:
diff changeset
1365 }
anatofuz
parents:
diff changeset
1366
anatofuz
parents:
diff changeset
1367 void Editline::SetAutoCompleteCallback(CompleteCallbackType callback,
anatofuz
parents:
diff changeset
1368 void *baton) {
anatofuz
parents:
diff changeset
1369 m_completion_callback = callback;
anatofuz
parents:
diff changeset
1370 m_completion_callback_baton = baton;
anatofuz
parents:
diff changeset
1371 }
anatofuz
parents:
diff changeset
1372
anatofuz
parents:
diff changeset
1373 void Editline::SetIsInputCompleteCallback(IsInputCompleteCallbackType callback,
anatofuz
parents:
diff changeset
1374 void *baton) {
anatofuz
parents:
diff changeset
1375 m_is_input_complete_callback = callback;
anatofuz
parents:
diff changeset
1376 m_is_input_complete_callback_baton = baton;
anatofuz
parents:
diff changeset
1377 }
anatofuz
parents:
diff changeset
1378
anatofuz
parents:
diff changeset
1379 bool Editline::SetFixIndentationCallback(FixIndentationCallbackType callback,
anatofuz
parents:
diff changeset
1380 void *baton,
anatofuz
parents:
diff changeset
1381 const char *indent_chars) {
anatofuz
parents:
diff changeset
1382 m_fix_indentation_callback = callback;
anatofuz
parents:
diff changeset
1383 m_fix_indentation_callback_baton = baton;
anatofuz
parents:
diff changeset
1384 m_fix_indentation_callback_chars = indent_chars;
anatofuz
parents:
diff changeset
1385 return false;
anatofuz
parents:
diff changeset
1386 }
anatofuz
parents:
diff changeset
1387
anatofuz
parents:
diff changeset
1388 bool Editline::GetLine(std::string &line, bool &interrupted) {
anatofuz
parents:
diff changeset
1389 ConfigureEditor(false);
anatofuz
parents:
diff changeset
1390 m_input_lines = std::vector<EditLineStringType>();
anatofuz
parents:
diff changeset
1391 m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
anatofuz
parents:
diff changeset
1392
anatofuz
parents:
diff changeset
1393 std::lock_guard<std::mutex> guard(m_output_mutex);
anatofuz
parents:
diff changeset
1394
anatofuz
parents:
diff changeset
1395 lldbassert(m_editor_status != EditorStatus::Editing);
anatofuz
parents:
diff changeset
1396 if (m_editor_status == EditorStatus::Interrupted) {
anatofuz
parents:
diff changeset
1397 m_editor_status = EditorStatus::Complete;
anatofuz
parents:
diff changeset
1398 interrupted = true;
anatofuz
parents:
diff changeset
1399 return true;
anatofuz
parents:
diff changeset
1400 }
anatofuz
parents:
diff changeset
1401
anatofuz
parents:
diff changeset
1402 SetCurrentLine(0);
anatofuz
parents:
diff changeset
1403 m_in_history = false;
anatofuz
parents:
diff changeset
1404 m_editor_status = EditorStatus::Editing;
anatofuz
parents:
diff changeset
1405 m_revert_cursor_index = -1;
anatofuz
parents:
diff changeset
1406
anatofuz
parents:
diff changeset
1407 int count;
anatofuz
parents:
diff changeset
1408 auto input = el_wgets(m_editline, &count);
anatofuz
parents:
diff changeset
1409
anatofuz
parents:
diff changeset
1410 interrupted = m_editor_status == EditorStatus::Interrupted;
anatofuz
parents:
diff changeset
1411 if (!interrupted) {
anatofuz
parents:
diff changeset
1412 if (input == nullptr) {
anatofuz
parents:
diff changeset
1413 fprintf(m_output_file, "\n");
anatofuz
parents:
diff changeset
1414 m_editor_status = EditorStatus::EndOfInput;
anatofuz
parents:
diff changeset
1415 } else {
anatofuz
parents:
diff changeset
1416 m_history_sp->Enter(input);
anatofuz
parents:
diff changeset
1417 #if LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
1418 line = m_utf8conv.to_bytes(SplitLines(input)[0]);
anatofuz
parents:
diff changeset
1419 #else
anatofuz
parents:
diff changeset
1420 line = SplitLines(input)[0];
anatofuz
parents:
diff changeset
1421 #endif
anatofuz
parents:
diff changeset
1422 m_editor_status = EditorStatus::Complete;
anatofuz
parents:
diff changeset
1423 }
anatofuz
parents:
diff changeset
1424 }
anatofuz
parents:
diff changeset
1425 return m_editor_status != EditorStatus::EndOfInput;
anatofuz
parents:
diff changeset
1426 }
anatofuz
parents:
diff changeset
1427
anatofuz
parents:
diff changeset
1428 bool Editline::GetLines(int first_line_number, StringList &lines,
anatofuz
parents:
diff changeset
1429 bool &interrupted) {
anatofuz
parents:
diff changeset
1430 ConfigureEditor(true);
anatofuz
parents:
diff changeset
1431
anatofuz
parents:
diff changeset
1432 // Print the initial input lines, then move the cursor back up to the start
anatofuz
parents:
diff changeset
1433 // of input
anatofuz
parents:
diff changeset
1434 SetBaseLineNumber(first_line_number);
anatofuz
parents:
diff changeset
1435 m_input_lines = std::vector<EditLineStringType>();
anatofuz
parents:
diff changeset
1436 m_input_lines.insert(m_input_lines.begin(), EditLineConstString(""));
anatofuz
parents:
diff changeset
1437
anatofuz
parents:
diff changeset
1438 std::lock_guard<std::mutex> guard(m_output_mutex);
anatofuz
parents:
diff changeset
1439 // Begin the line editing loop
anatofuz
parents:
diff changeset
1440 DisplayInput();
anatofuz
parents:
diff changeset
1441 SetCurrentLine(0);
anatofuz
parents:
diff changeset
1442 MoveCursor(CursorLocation::BlockEnd, CursorLocation::BlockStart);
anatofuz
parents:
diff changeset
1443 m_editor_status = EditorStatus::Editing;
anatofuz
parents:
diff changeset
1444 m_in_history = false;
anatofuz
parents:
diff changeset
1445
anatofuz
parents:
diff changeset
1446 m_revert_cursor_index = -1;
anatofuz
parents:
diff changeset
1447 while (m_editor_status == EditorStatus::Editing) {
anatofuz
parents:
diff changeset
1448 int count;
anatofuz
parents:
diff changeset
1449 m_current_line_rows = -1;
anatofuz
parents:
diff changeset
1450 el_wpush(m_editline, EditLineConstString(
anatofuz
parents:
diff changeset
1451 "\x1b[^")); // Revert to the existing line content
anatofuz
parents:
diff changeset
1452 el_wgets(m_editline, &count);
anatofuz
parents:
diff changeset
1453 }
anatofuz
parents:
diff changeset
1454
anatofuz
parents:
diff changeset
1455 interrupted = m_editor_status == EditorStatus::Interrupted;
anatofuz
parents:
diff changeset
1456 if (!interrupted) {
anatofuz
parents:
diff changeset
1457 // Save the completed entry in history before returning
anatofuz
parents:
diff changeset
1458 m_history_sp->Enter(CombineLines(m_input_lines).c_str());
anatofuz
parents:
diff changeset
1459
anatofuz
parents:
diff changeset
1460 lines = GetInputAsStringList();
anatofuz
parents:
diff changeset
1461 }
anatofuz
parents:
diff changeset
1462 return m_editor_status != EditorStatus::EndOfInput;
anatofuz
parents:
diff changeset
1463 }
anatofuz
parents:
diff changeset
1464
anatofuz
parents:
diff changeset
1465 void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
anatofuz
parents:
diff changeset
1466 std::lock_guard<std::mutex> guard(m_output_mutex);
anatofuz
parents:
diff changeset
1467 if (m_editor_status == EditorStatus::Editing) {
anatofuz
parents:
diff changeset
1468 MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart);
anatofuz
parents:
diff changeset
1469 fprintf(m_output_file, ANSI_CLEAR_BELOW);
anatofuz
parents:
diff changeset
1470 }
anatofuz
parents:
diff changeset
1471 stream->Write(s, len);
anatofuz
parents:
diff changeset
1472 stream->Flush();
anatofuz
parents:
diff changeset
1473 if (m_editor_status == EditorStatus::Editing) {
anatofuz
parents:
diff changeset
1474 DisplayInput();
anatofuz
parents:
diff changeset
1475 MoveCursor(CursorLocation::BlockEnd, CursorLocation::EditingCursor);
anatofuz
parents:
diff changeset
1476 }
anatofuz
parents:
diff changeset
1477 }
anatofuz
parents:
diff changeset
1478
anatofuz
parents:
diff changeset
1479 bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
anatofuz
parents:
diff changeset
1480 #if !LLDB_EDITLINE_USE_WCHAR
anatofuz
parents:
diff changeset
1481 if (ch == (char)EOF)
anatofuz
parents:
diff changeset
1482 return false;
anatofuz
parents:
diff changeset
1483
anatofuz
parents:
diff changeset
1484 out = (unsigned char)ch;
anatofuz
parents:
diff changeset
1485 return true;
anatofuz
parents:
diff changeset
1486 #else
anatofuz
parents:
diff changeset
1487 std::codecvt_utf8<wchar_t> cvt;
anatofuz
parents:
diff changeset
1488 llvm::SmallString<4> input;
anatofuz
parents:
diff changeset
1489 for (;;) {
anatofuz
parents:
diff changeset
1490 const char *from_next;
anatofuz
parents:
diff changeset
1491 wchar_t *to_next;
anatofuz
parents:
diff changeset
1492 std::mbstate_t state = std::mbstate_t();
anatofuz
parents:
diff changeset
1493 input.push_back(ch);
anatofuz
parents:
diff changeset
1494 switch (cvt.in(state, input.begin(), input.end(), from_next, &out, &out + 1,
anatofuz
parents:
diff changeset
1495 to_next)) {
anatofuz
parents:
diff changeset
1496 case std::codecvt_base::ok:
anatofuz
parents:
diff changeset
1497 return out != (int)WEOF;
anatofuz
parents:
diff changeset
1498
anatofuz
parents:
diff changeset
1499 case std::codecvt_base::error:
anatofuz
parents:
diff changeset
1500 case std::codecvt_base::noconv:
anatofuz
parents:
diff changeset
1501 return false;
anatofuz
parents:
diff changeset
1502
anatofuz
parents:
diff changeset
1503 case std::codecvt_base::partial:
anatofuz
parents:
diff changeset
1504 lldb::ConnectionStatus status;
anatofuz
parents:
diff changeset
1505 size_t read_count = m_input_connection.Read(
anatofuz
parents:
diff changeset
1506 &ch, 1, std::chrono::seconds(0), status, nullptr);
anatofuz
parents:
diff changeset
1507 if (read_count == 0)
anatofuz
parents:
diff changeset
1508 return false;
anatofuz
parents:
diff changeset
1509 break;
anatofuz
parents:
diff changeset
1510 }
anatofuz
parents:
diff changeset
1511 }
anatofuz
parents:
diff changeset
1512 #endif
anatofuz
parents:
diff changeset
1513 }