LLVM API Documentation
00001 //===-- LineEditor.cpp - line editor --------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "llvm/LineEditor/LineEditor.h" 00011 #include "llvm/ADT/SmallString.h" 00012 #include "llvm/Config/config.h" 00013 #include "llvm/Support/Path.h" 00014 #include "llvm/Support/raw_ostream.h" 00015 #include <stdio.h> 00016 #ifdef HAVE_LIBEDIT 00017 #include <histedit.h> 00018 #endif 00019 00020 using namespace llvm; 00021 00022 std::string LineEditor::getDefaultHistoryPath(StringRef ProgName) { 00023 SmallString<32> Path; 00024 if (sys::path::home_directory(Path)) { 00025 sys::path::append(Path, "." + ProgName + "-history"); 00026 return Path.str(); 00027 } 00028 return std::string(); 00029 } 00030 00031 LineEditor::CompleterConcept::~CompleterConcept() {} 00032 LineEditor::ListCompleterConcept::~ListCompleterConcept() {} 00033 00034 std::string LineEditor::ListCompleterConcept::getCommonPrefix( 00035 const std::vector<Completion> &Comps) { 00036 assert(!Comps.empty()); 00037 00038 std::string CommonPrefix = Comps[0].TypedText; 00039 for (std::vector<Completion>::const_iterator I = Comps.begin() + 1, 00040 E = Comps.end(); 00041 I != E; ++I) { 00042 size_t Len = std::min(CommonPrefix.size(), I->TypedText.size()); 00043 size_t CommonLen = 0; 00044 for (; CommonLen != Len; ++CommonLen) { 00045 if (CommonPrefix[CommonLen] != I->TypedText[CommonLen]) 00046 break; 00047 } 00048 CommonPrefix.resize(CommonLen); 00049 } 00050 return CommonPrefix; 00051 } 00052 00053 LineEditor::CompletionAction 00054 LineEditor::ListCompleterConcept::complete(StringRef Buffer, size_t Pos) const { 00055 CompletionAction Action; 00056 std::vector<Completion> Comps = getCompletions(Buffer, Pos); 00057 if (Comps.empty()) { 00058 Action.Kind = CompletionAction::AK_ShowCompletions; 00059 return Action; 00060 } 00061 00062 std::string CommonPrefix = getCommonPrefix(Comps); 00063 00064 // If the common prefix is non-empty we can simply insert it. If there is a 00065 // single completion, this will insert the full completion. If there is more 00066 // than one, this might be enough information to jog the user's memory but if 00067 // not the user can also hit tab again to see the completions because the 00068 // common prefix will then be empty. 00069 if (CommonPrefix.empty()) { 00070 Action.Kind = CompletionAction::AK_ShowCompletions; 00071 for (std::vector<Completion>::iterator I = Comps.begin(), E = Comps.end(); 00072 I != E; ++I) 00073 Action.Completions.push_back(I->DisplayText); 00074 } else { 00075 Action.Kind = CompletionAction::AK_Insert; 00076 Action.Text = CommonPrefix; 00077 } 00078 00079 return Action; 00080 } 00081 00082 LineEditor::CompletionAction LineEditor::getCompletionAction(StringRef Buffer, 00083 size_t Pos) const { 00084 if (!Completer) { 00085 CompletionAction Action; 00086 Action.Kind = CompletionAction::AK_ShowCompletions; 00087 return Action; 00088 } 00089 00090 return Completer->complete(Buffer, Pos); 00091 } 00092 00093 #ifdef HAVE_LIBEDIT 00094 00095 // libedit-based implementation. 00096 00097 struct LineEditor::InternalData { 00098 LineEditor *LE; 00099 00100 History *Hist; 00101 EditLine *EL; 00102 00103 unsigned PrevCount; 00104 std::string ContinuationOutput; 00105 00106 FILE *Out; 00107 }; 00108 00109 static const char *ElGetPromptFn(EditLine *EL) { 00110 LineEditor::InternalData *Data; 00111 if (el_get(EL, EL_CLIENTDATA, &Data) == 0) 00112 return Data->LE->getPrompt().c_str(); 00113 return "> "; 00114 } 00115 00116 // Handles tab completion. 00117 // 00118 // This function is really horrible. But since the alternative is to get into 00119 // the line editor business, here we are. 00120 static unsigned char ElCompletionFn(EditLine *EL, int ch) { 00121 LineEditor::InternalData *Data; 00122 if (el_get(EL, EL_CLIENTDATA, &Data) == 0) { 00123 if (!Data->ContinuationOutput.empty()) { 00124 // This is the continuation of the AK_ShowCompletions branch below. 00125 FILE *Out = Data->Out; 00126 00127 // Print the required output (see below). 00128 ::fwrite(Data->ContinuationOutput.c_str(), 00129 Data->ContinuationOutput.size(), 1, Out); 00130 00131 // Push a sequence of Ctrl-B characters to move the cursor back to its 00132 // original position. 00133 std::string Prevs(Data->PrevCount, '\02'); 00134 ::el_push(EL, const_cast<char *>(Prevs.c_str())); 00135 00136 Data->ContinuationOutput.clear(); 00137 00138 return CC_REFRESH; 00139 } 00140 00141 const LineInfo *LI = ::el_line(EL); 00142 LineEditor::CompletionAction Action = Data->LE->getCompletionAction( 00143 StringRef(LI->buffer, LI->lastchar - LI->buffer), 00144 LI->cursor - LI->buffer); 00145 switch (Action.Kind) { 00146 case LineEditor::CompletionAction::AK_Insert: 00147 ::el_insertstr(EL, Action.Text.c_str()); 00148 return CC_REFRESH; 00149 00150 case LineEditor::CompletionAction::AK_ShowCompletions: 00151 if (Action.Completions.empty()) { 00152 return CC_REFRESH_BEEP; 00153 } else { 00154 // Push a Ctrl-E and a tab. The Ctrl-E causes libedit to move the cursor 00155 // to the end of the line, so that when we emit a newline we will be on 00156 // a new blank line. The tab causes libedit to call this function again 00157 // after moving the cursor. There doesn't seem to be anything we can do 00158 // from here to cause libedit to move the cursor immediately. This will 00159 // break horribly if the user has rebound their keys, so for now we do 00160 // not permit user rebinding. 00161 ::el_push(EL, const_cast<char *>("\05\t")); 00162 00163 // This assembles the output for the continuation block above. 00164 raw_string_ostream OS(Data->ContinuationOutput); 00165 00166 // Move cursor to a blank line. 00167 OS << "\n"; 00168 00169 // Emit the completions. 00170 for (std::vector<std::string>::iterator I = Action.Completions.begin(), 00171 E = Action.Completions.end(); 00172 I != E; ++I) { 00173 OS << *I << "\n"; 00174 } 00175 00176 // Fool libedit into thinking nothing has changed. Reprint its prompt 00177 // and the user input. Note that the cursor will remain at the end of 00178 // the line after this. 00179 OS << Data->LE->getPrompt() 00180 << StringRef(LI->buffer, LI->lastchar - LI->buffer); 00181 00182 // This is the number of characters we need to tell libedit to go back: 00183 // the distance between end of line and the original cursor position. 00184 Data->PrevCount = LI->lastchar - LI->cursor; 00185 00186 return CC_REFRESH; 00187 } 00188 } 00189 } 00190 return CC_ERROR; 00191 } 00192 00193 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In, 00194 FILE *Out, FILE *Err) 00195 : Prompt((ProgName + "> ").str()), HistoryPath(HistoryPath), 00196 Data(new InternalData) { 00197 if (HistoryPath.empty()) 00198 this->HistoryPath = getDefaultHistoryPath(ProgName); 00199 00200 Data->LE = this; 00201 Data->Out = Out; 00202 00203 Data->Hist = ::history_init(); 00204 assert(Data->Hist); 00205 00206 Data->EL = ::el_init(ProgName.str().c_str(), In, Out, Err); 00207 assert(Data->EL); 00208 00209 ::el_set(Data->EL, EL_PROMPT, ElGetPromptFn); 00210 ::el_set(Data->EL, EL_EDITOR, "emacs"); 00211 ::el_set(Data->EL, EL_HIST, history, Data->Hist); 00212 ::el_set(Data->EL, EL_ADDFN, "tab_complete", "Tab completion function", 00213 ElCompletionFn); 00214 ::el_set(Data->EL, EL_BIND, "\t", "tab_complete", NULL); 00215 ::el_set(Data->EL, EL_BIND, "^r", "em-inc-search-prev", 00216 NULL); // Cycle through backwards search, entering string 00217 ::el_set(Data->EL, EL_BIND, "^w", "ed-delete-prev-word", 00218 NULL); // Delete previous word, behave like bash does. 00219 ::el_set(Data->EL, EL_BIND, "\033[3~", "ed-delete-next-char", 00220 NULL); // Fix the delete key. 00221 ::el_set(Data->EL, EL_CLIENTDATA, Data.get()); 00222 00223 HistEvent HE; 00224 ::history(Data->Hist, &HE, H_SETSIZE, 800); 00225 ::history(Data->Hist, &HE, H_SETUNIQUE, 1); 00226 loadHistory(); 00227 } 00228 00229 LineEditor::~LineEditor() { 00230 saveHistory(); 00231 00232 ::history_end(Data->Hist); 00233 ::el_end(Data->EL); 00234 ::fwrite("\n", 1, 1, Data->Out); 00235 } 00236 00237 void LineEditor::saveHistory() { 00238 if (!HistoryPath.empty()) { 00239 HistEvent HE; 00240 ::history(Data->Hist, &HE, H_SAVE, HistoryPath.c_str()); 00241 } 00242 } 00243 00244 void LineEditor::loadHistory() { 00245 if (!HistoryPath.empty()) { 00246 HistEvent HE; 00247 ::history(Data->Hist, &HE, H_LOAD, HistoryPath.c_str()); 00248 } 00249 } 00250 00251 Optional<std::string> LineEditor::readLine() const { 00252 // Call el_gets to prompt the user and read the user's input. 00253 int LineLen = 0; 00254 const char *Line = ::el_gets(Data->EL, &LineLen); 00255 00256 // Either of these may mean end-of-file. 00257 if (!Line || LineLen == 0) 00258 return Optional<std::string>(); 00259 00260 // Strip any newlines off the end of the string. 00261 while (LineLen > 0 && 00262 (Line[LineLen - 1] == '\n' || Line[LineLen - 1] == '\r')) 00263 --LineLen; 00264 00265 HistEvent HE; 00266 if (LineLen > 0) 00267 ::history(Data->Hist, &HE, H_ENTER, Line); 00268 00269 return std::string(Line, LineLen); 00270 } 00271 00272 #else 00273 00274 // Simple fgets-based implementation. 00275 00276 struct LineEditor::InternalData { 00277 FILE *In; 00278 FILE *Out; 00279 }; 00280 00281 LineEditor::LineEditor(StringRef ProgName, StringRef HistoryPath, FILE *In, 00282 FILE *Out, FILE *Err) 00283 : Prompt((ProgName + "> ").str()), Data(new InternalData) { 00284 Data->In = In; 00285 Data->Out = Out; 00286 } 00287 00288 LineEditor::~LineEditor() { 00289 ::fwrite("\n", 1, 1, Data->Out); 00290 } 00291 00292 void LineEditor::saveHistory() {} 00293 void LineEditor::loadHistory() {} 00294 00295 Optional<std::string> LineEditor::readLine() const { 00296 ::fprintf(Data->Out, "%s", Prompt.c_str()); 00297 00298 std::string Line; 00299 do { 00300 char Buf[64]; 00301 char *Res = ::fgets(Buf, sizeof(Buf), Data->In); 00302 if (!Res) { 00303 if (Line.empty()) 00304 return Optional<std::string>(); 00305 else 00306 return Line; 00307 } 00308 Line.append(Buf); 00309 } while (Line.empty() || 00310 (Line[Line.size() - 1] != '\n' && Line[Line.size() - 1] != '\r')); 00311 00312 while (!Line.empty() && 00313 (Line[Line.size() - 1] == '\n' || Line[Line.size() - 1] == '\r')) 00314 Line.resize(Line.size() - 1); 00315 00316 return Line; 00317 } 00318 00319 #endif