Home | History | Annotate | Download | only in src
      1 // Copyright 2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 
     29 #include <cstdio>  // NOLINT
     30 #include <readline/readline.h> // NOLINT
     31 #include <readline/history.h> // NOLINT
     32 
     33 
     34 #include "d8.h"
     35 
     36 
     37 // There are incompatibilities between different versions and different
     38 // implementations of readline.  This smooths out one known incompatibility.
     39 #if RL_READLINE_VERSION >= 0x0500
     40 #define completion_matches rl_completion_matches
     41 #endif
     42 
     43 
     44 namespace v8 {
     45 
     46 
     47 class ReadLineEditor: public LineEditor {
     48  public:
     49   ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
     50   virtual i::SmartPointer<char> Prompt(const char* prompt);
     51   virtual bool Open();
     52   virtual bool Close();
     53   virtual void AddHistory(const char* str);
     54  private:
     55   static char** AttemptedCompletion(const char* text, int start, int end);
     56   static char* CompletionGenerator(const char* text, int state);
     57   static char kWordBreakCharacters[];
     58 };
     59 
     60 
     61 static ReadLineEditor read_line_editor;
     62 char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
     63     '\\', '\'', '`', '@', '.', '>', '<', '=', ';', '|', '&', '{', '(',
     64     '\0'};
     65 
     66 
     67 bool ReadLineEditor::Open() {
     68   rl_initialize();
     69   rl_attempted_completion_function = AttemptedCompletion;
     70   rl_completer_word_break_characters = kWordBreakCharacters;
     71   rl_bind_key('\t', rl_complete);
     72   using_history();
     73   return read_history(Shell::kHistoryFileName) == 0;
     74 }
     75 
     76 
     77 bool ReadLineEditor::Close() {
     78   return write_history(Shell::kHistoryFileName) == 0;
     79 }
     80 
     81 
     82 i::SmartPointer<char> ReadLineEditor::Prompt(const char* prompt) {
     83   char* result = readline(prompt);
     84   return i::SmartPointer<char>(result);
     85 }
     86 
     87 
     88 void ReadLineEditor::AddHistory(const char* str) {
     89   add_history(str);
     90 }
     91 
     92 
     93 char** ReadLineEditor::AttemptedCompletion(const char* text,
     94                                            int start,
     95                                            int end) {
     96   char** result = completion_matches(text, CompletionGenerator);
     97   rl_attempted_completion_over = true;
     98   return result;
     99 }
    100 
    101 
    102 char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
    103   static unsigned current_index;
    104   static Persistent<Array> current_completions;
    105   if (state == 0) {
    106     i::SmartPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
    107     HandleScope scope;
    108     Handle<Array> completions =
    109       Shell::GetCompletions(String::New(text), String::New(*full_text));
    110     current_completions = Persistent<Array>::New(completions);
    111     current_index = 0;
    112   }
    113   if (current_index < current_completions->Length()) {
    114     HandleScope scope;
    115     Handle<Integer> index = Integer::New(current_index);
    116     Handle<Value> str_obj = current_completions->Get(index);
    117     current_index++;
    118     String::Utf8Value str(str_obj);
    119     return strdup(*str);
    120   } else {
    121     current_completions.Dispose();
    122     current_completions.Clear();
    123     return NULL;
    124   }
    125 }
    126 
    127 
    128 }  // namespace v8
    129