blob: 08395e53de103aa481aa2752bdf94db15bdbc0ad [file] [log] [blame]
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00001// 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
ager@chromium.org8bb60582008-12-11 12:02:20 +000029#include <cstdio> // NOLINT
ager@chromium.org5c838252010-02-19 08:53:10 +000030#include <readline/readline.h> // NOLINT
31#include <readline/history.h> // NOLINT
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000032
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000033// The readline includes leaves RETURN defined which breaks V8 compilation.
34#undef RETURN
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000035
36#include "d8.h"
37
38
ager@chromium.org8bb60582008-12-11 12:02:20 +000039// There are incompatibilities between different versions and different
ager@chromium.org32912102009-01-16 10:38:43 +000040// implementations of readline. This smooths out one known incompatibility.
ager@chromium.org8bb60582008-12-11 12:02:20 +000041#if RL_READLINE_VERSION >= 0x0500
42#define completion_matches rl_completion_matches
43#endif
44
45
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000046namespace v8 {
47
48
49class ReadLineEditor: public LineEditor {
50 public:
51 ReadLineEditor() : LineEditor(LineEditor::READLINE, "readline") { }
52 virtual i::SmartPointer<char> Prompt(const char* prompt);
53 virtual bool Open();
54 virtual bool Close();
55 virtual void AddHistory(const char* str);
56 private:
57 static char** AttemptedCompletion(const char* text, int start, int end);
58 static char* CompletionGenerator(const char* text, int state);
59 static char kWordBreakCharacters[];
60};
61
62
63static ReadLineEditor read_line_editor;
64char ReadLineEditor::kWordBreakCharacters[] = {' ', '\t', '\n', '"',
65 '\\', '\'', '`', '@', '.', '>', '<', '=', ';', '|', '&', '{', '(',
66 '\0'};
67
68
69bool ReadLineEditor::Open() {
70 rl_initialize();
71 rl_attempted_completion_function = AttemptedCompletion;
72 rl_completer_word_break_characters = kWordBreakCharacters;
73 rl_bind_key('\t', rl_complete);
74 using_history();
75 return read_history(Shell::kHistoryFileName) == 0;
76}
77
78
79bool ReadLineEditor::Close() {
80 return write_history(Shell::kHistoryFileName) == 0;
81}
82
83
84i::SmartPointer<char> ReadLineEditor::Prompt(const char* prompt) {
85 char* result = readline(prompt);
86 return i::SmartPointer<char>(result);
87}
88
89
90void ReadLineEditor::AddHistory(const char* str) {
91 add_history(str);
92}
93
94
95char** ReadLineEditor::AttemptedCompletion(const char* text,
96 int start,
97 int end) {
ager@chromium.org8bb60582008-12-11 12:02:20 +000098 char** result = completion_matches(text, CompletionGenerator);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000099 rl_attempted_completion_over = true;
100 return result;
101}
102
103
104char* ReadLineEditor::CompletionGenerator(const char* text, int state) {
105 static unsigned current_index;
106 static Persistent<Array> current_completions;
107 if (state == 0) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000108 i::SmartPointer<char> full_text(i::StrNDup(rl_line_buffer, rl_point));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000109 HandleScope scope;
110 Handle<Array> completions =
111 Shell::GetCompletions(String::New(text), String::New(*full_text));
112 current_completions = Persistent<Array>::New(completions);
113 current_index = 0;
114 }
115 if (current_index < current_completions->Length()) {
116 HandleScope scope;
117 Handle<Integer> index = Integer::New(current_index);
118 Handle<Value> str_obj = current_completions->Get(index);
119 current_index++;
120 String::Utf8Value str(str_obj);
121 return strdup(*str);
122 } else {
123 current_completions.Dispose();
124 current_completions.Clear();
125 return NULL;
126 }
127}
128
129
130} // namespace v8